/**
* Aptana Studio
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions).
* Please see the license.html included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.editor.php.internal.builder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import com.aptana.core.logging.IdeLog;
import com.aptana.editor.php.PHPEditorPlugin;
import com.aptana.editor.php.internal.core.builder.IBuildPath;
import com.aptana.editor.php.internal.core.builder.IBuildPathChangeListener;
import com.aptana.editor.php.internal.core.builder.IBuildPathResource;
import com.aptana.editor.php.internal.core.builder.IDirectory;
import com.aptana.editor.php.internal.core.builder.IModule;
/**
* Abstract build path.
*
* @author Denis Denisenko
*/
public abstract class AbstractBuildPath implements IBuildPath
{
/**
* Listeners.
*/
private Set<IBuildPathChangeListener> listeners = new HashSet<IBuildPathChangeListener>();
/**
* Build path dependencies.
*/
private Set<IBuildPath> dependencies = new LinkedHashSet<IBuildPath>();
/**
* {@inheritDoc}
*/
public void addBuildPathChangeListener(IBuildPathChangeListener listener)
{
synchronized (listeners)
{
listeners.add(listener);
}
}
/**
* {@inheritDoc}
*/
public synchronized void removeBuildPathChangeListener(IBuildPathChangeListener listener)
{
synchronized (listeners)
{
listeners.remove(listener);
}
}
/**
* {@inheritDoc}
*/
public synchronized void addDependency(IBuildPath dependency)
{
dependencies.add(dependency);
}
/**
* {@inheritDoc}
*/
public synchronized Set<IBuildPath> getDependencies()
{
return Collections.unmodifiableSet(dependencies);
}
/**
* {@inheritDoc}
*/
public synchronized void removeDependency(IBuildPath dependency)
{
dependencies.remove(dependency);
}
/**
* {@inheritDoc}
*/
public void clearDependencies()
{
dependencies.clear();
}
/**
* {@inheritDoc}
*/
public synchronized IModule resolveRelativePath(IModule baseModule, IPath relativePath)
{
IPath baseModulePath = getResourcePath(baseModule);
if (baseModulePath == null)
{
return null;
}
if (relativePath.segmentCount() == 0)
{
return baseModule;
}
IPath basePath = null;
if (baseModulePath.segmentCount() <= 1)
{
basePath = (new Path("")).makeAbsolute(); //$NON-NLS-1$
}
else
{
basePath = baseModulePath.removeLastSegments(1);
}
IPath resolvedPath = basePath.append(relativePath);
if (resolvedPath.segmentCount() == 0)
{
return null;
}
IModule module = getModuleByPath(resolvedPath);
if (module == null && (relativePath.segments()[0].startsWith("."))) //$NON-NLS-1$
{
return null;
}
// if no module is found relatively to the current file, trying to search it relatively to the project root
if (module == null)
{
module = getModuleByPath(relativePath);
}
// if no module found in this build-path, checking the build paths, current build path depends from.
if (module == null)
{
for (IBuildPath currentBuildPath : getDependencies())
{
module = currentBuildPath.getModuleByPath(relativePath);
if (module != null)
{
return module;
}
}
}
return module;
}
/**
* {@inheritDoc}
*/
public List<IBuildPathResource> resolveContainerRelativePath(IModule baseModule, IPath relativePath)
{
IPath baseModulePath = getResourcePath(baseModule);
if (baseModulePath == null)
{
return null;
}
IPath basePath = null;
if (baseModulePath.segmentCount() <= 1)
{
basePath = (new Path("")).makeAbsolute(); //$NON-NLS-1$
}
else
{
basePath = baseModulePath.removeLastSegments(1);
}
IPath resolvedPath = basePath.append(relativePath);
List<IBuildPathResource> result = new ArrayList<IBuildPathResource>();
List<IModule> currentBuildPathModules = getModulesByPath(resolvedPath);
if (currentBuildPathModules != null)
{
result.addAll(currentBuildPathModules);
}
List<IDirectory> dirs = getSubdirectoriesByPath(resolvedPath);
if (dirs != null)
{
result.addAll(dirs);
}
// if no module found in this class, checking the build paths, current build path depends from.
// but first getting rid of the "./" and "../" paths
if (relativePath.segmentCount() >= 1
&& (relativePath.segment(0).length() > 0 && relativePath.segment(0).charAt(0) == '.'))
{
return result;
}
for (IBuildPath currentBuildPath : getDependencies())
{
currentBuildPathModules = currentBuildPath.getModulesByPath(relativePath);
if (currentBuildPathModules != null)
{
result.addAll(currentBuildPathModules);
}
dirs = currentBuildPath.getSubdirectoriesByPath(relativePath);
if (dirs != null)
{
result.addAll(dirs);
}
}
return result;
}
/**
* Notifies build path modules structure or contents changed before the change.
*
* @param added
* - added modules.
* @param changed
* - changed modules.
* @param removed
* - removed modules.
* @param addedDirectories
* - added directories.
* @param removedDirectories
* - removed directories.
*/
protected void notifyChangedBefore(List<IModule> changed, List<IModule> removed, List<IDirectory> removedDirectories)
{
IWorkspace workspace = ResourcesPlugin.getWorkspace();
if (!workspace.isAutoBuilding())
{
return;
}
Set<IBuildPathChangeListener> buildPathListeners = null;
synchronized (listeners)
{
buildPathListeners = new LinkedHashSet<IBuildPathChangeListener>(listeners);
}
for (IBuildPathChangeListener listener : buildPathListeners)
{
try
{
listener.changedBefore(changed, removed, removedDirectories);
}
catch (Throwable th)
{
IdeLog.logError(PHPEditorPlugin.getDefault(), "Unable notifying build path change listener", th); //$NON-NLS-1$
}
}
}
/**
* Notifies build path modules structure or contents changed after the change.
*
* @param added
* - added modules.
* @param changed
* - changed modules.
* @param removed
* - removed modules.
* @param addedDirectories
* - added directories.
* @param removedDirectories
* - removed directories.
*/
protected void notifyChangedAfter(List<IModule> added, List<IModule> changed, List<IModule> removed,
List<IDirectory> addedDirectories, List<IDirectory> removedDirectories)
{
IWorkspace workspace = ResourcesPlugin.getWorkspace();
if (!workspace.isAutoBuilding())
{
return;
}
Set<IBuildPathChangeListener> buildPathListeners = null;
synchronized (listeners)
{
buildPathListeners = new LinkedHashSet<IBuildPathChangeListener>(listeners);
}
for (IBuildPathChangeListener listener : buildPathListeners)
{
try
{
listener.changedAfter(added, changed, removed, addedDirectories, removedDirectories);
}
catch (Throwable th)
{
IdeLog.logError(PHPEditorPlugin.getDefault(), "Unable notifying build path change listener", th); //$NON-NLS-1$
}
}
}
}