/**********************************************************************
* Copyright (c) 2005-2009 ant4eclipse project team.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nils Hartmann, Daniel Kasmeroglu, Gerd Wuetherich
**********************************************************************/
package org.ant4eclipse.lib.platform.internal.model.resource;
import org.ant4eclipse.lib.core.Assure;
import org.ant4eclipse.lib.core.service.ServiceRegistryAccess;
import org.ant4eclipse.lib.core.util.Utilities;
import org.ant4eclipse.lib.platform.internal.model.resource.role.NatureNicknameRegistry;
import org.ant4eclipse.lib.platform.model.resource.BuildCommand;
import org.ant4eclipse.lib.platform.model.resource.EclipseProject;
import org.ant4eclipse.lib.platform.model.resource.ProjectNature;
import org.ant4eclipse.lib.platform.model.resource.Workspace;
import org.ant4eclipse.lib.platform.model.resource.role.AbstractProjectRole;
import org.ant4eclipse.lib.platform.model.resource.role.ProjectRole;
import java.io.File;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* Encapsultes a project. A project contains a workspace and is represented by a directory in this workspace. A project
* can have multiple natures and multiple roles.
*
* @author Gerd Wütherich (gerd@gerd-wuetherich.de)
*/
public final class EclipseProjectImpl implements EclipseProject {
/** The name of the projects <tt>.settings</tt> folder */
public static final String SETTINGS_FOLDER_NAME = ".settings";
/** the workspace that contains this project */
private Workspace _workspace;
/** the file that represents this project */
private File _projectDirectory;
/** the project name specified in the project description */
private String _specifiedName;
/** the <tt>.settings</tt> folder of the project or <tt>null<tt> if there is no <tt>.settings</tt> folder */
private File _settingsFolder;
/** the project comment */
private String _comment;
/** the list of project natures */
private List<ProjectNature> _natures;
/** the list of project roles */
private List<ProjectRole> _roles;
/** the list of buildCommands */
private List<BuildCommand> _buildCommands;
/** the referenced project specified in the project description */
private List<String> _referencedProjects;
/** the linked resources specified in the project description */
private List<LinkedResourceImpl> _linkedResources;
/** the names of the linked resource. used for the mapping */
private List<String> _linkedResourceNames;
/**
* Creates a new instance of type project.
*
* @param workspace
* the workspace
* @param projectName
* the name of the project
*/
public EclipseProjectImpl(Workspace workspace, File projectDirectory) {
Assure.isDirectory("projectDirectory", projectDirectory);
this._workspace = workspace;
this._projectDirectory = Utilities.getCanonicalFile(projectDirectory);
this._natures = new LinkedList<ProjectNature>();
this._roles = new LinkedList<ProjectRole>();
this._buildCommands = new LinkedList<BuildCommand>();
this._referencedProjects = new LinkedList<String>();
this._linkedResources = new LinkedList<LinkedResourceImpl>();
this._linkedResourceNames = new LinkedList<String>();
File settingsFolder = getChild(SETTINGS_FOLDER_NAME);
this._settingsFolder = (settingsFolder.isDirectory() ? settingsFolder : null);
}
/**
* {@inheritDoc}
*/
public String getSpecifiedName() {
return this._specifiedName;
}
/**
* @param specifiedName
* The specifiedName to set.
*/
public void setSpecifiedName(String specifiedName) {
this._specifiedName = specifiedName;
}
/**
* {@inheritDoc}
*/
public String getComment() {
return this._comment;
}
/**
* @param comment
* The comment to set.
*/
public void setComment(String comment) {
this._comment = comment;
}
/**
* {@inheritDoc}
*/
public String getFolderName() {
return this._projectDirectory.getName();
}
/**
* {@inheritDoc}
*/
public File getFolder() {
return this._projectDirectory;
}
/**
* {@inheritDoc}
*/
public File getFolder(PathStyle pathstyle) {
Assure.notNull("pathstyle", pathstyle);
if (pathstyle == PathStyle.PROJECT_RELATIVE_WITHOUT_LEADING_PROJECT_NAME) {
return new File(".");
} else if (pathstyle == PathStyle.PROJECT_RELATIVE_WITH_LEADING_PROJECT_NAME) {
return new File(this._projectDirectory.getName());
} else /* if (pathstyle == PathStyle.ABSOLUTE) */{
return this._projectDirectory.getAbsoluteFile();
}
}
/**
* {@inheritDoc}
*/
public boolean exists() {
return this._projectDirectory.isDirectory();
}
/**
* {@inheritDoc}
*/
public boolean hasChild(String path) {
Assure.notNull("path", path);
File child = getChild(path);
return child.exists();
}
/**
* {@inheritDoc}
*/
public File getChild(String path) {
return getChild(path, PathStyle.ABSOLUTE);
}
/**
* {@inheritDoc}
*/
public File[] getChildren(String[] path) {
return getChildren(path, PathStyle.ABSOLUTE);
}
/**
* {@inheritDoc}
*/
public File[] getChildren(String[] path, PathStyle relative) {
Assure.notNull("path", path);
File[] result = new File[path.length];
for (int i = 0; i < result.length; i++) {
result[i] = getChild(path[i], relative);
}
return result;
}
protected boolean hasSettingsFolder() {
return this._settingsFolder != null;
}
/**
* {@inheritDoc}
*/
public boolean hasSettingsFile(String settingsFileName) {
// check if settings folder exists
if (!hasSettingsFolder()) {
return false;
}
File settingsFile = new File(this._settingsFolder, settingsFileName);
// is it an existing file?
return settingsFile.isFile();
}
/**
* {@inheritDoc}
*/
public File getSettingsFile(String settingsFileName) throws RuntimeException {
Assure.notNull("settingsFileName", settingsFileName);
Assure.assertTrue(hasSettingsFolder(), "The project '" + getFolderName() + "' must have a .settings folder");
File settingsFile = new File(this._settingsFolder, settingsFileName);
if (!settingsFile.exists()) {
throw new RuntimeException("Settings File '" + settingsFileName + "' not found in project '" + getFolderName()
+ "'");
}
if (!settingsFile.isFile()) {
throw new RuntimeException("Settings File '" + settingsFile + "' in project '" + getFolderName()
+ "' is not a file");
}
return settingsFile;
}
/**
* {@inheritDoc}
*/
public File getChild(String path, PathStyle pathstyle) {
Assure.notNull("path", path);
String name = path;
String rest = null;
int idx = firstFileSeparator(path);
if (idx != -1) {
name = path.substring(0, idx);
rest = path.substring(idx + 1);
}
// handle linked resource
if (isLinkedResource(name)) {
LinkedResourceImpl resource = getLinkedResource(name);
if ((pathstyle != PathStyle.ABSOLUTE) && (resource.getRelativeLocation() == null)) {
return (new File(resource.getLocation()));
}
File result = pathstyle != PathStyle.ABSOLUTE ? new File(getFolder(), resource.getRelativeLocation()) : new File(
resource.getLocation());
if (rest != null) {
result = new File(result, rest);
}
if ((pathstyle == PathStyle.ABSOLUTE) && (!result.isAbsolute())) {
result = new File(this._projectDirectory, result.getPath());
}
// TODO: remove
if (!result.exists()) {
throw new RuntimeException(result.getAbsolutePath());
}
//
return result;
}
//
if (pathstyle == PathStyle.PROJECT_RELATIVE_WITHOUT_LEADING_PROJECT_NAME) {
if (path.length() == 0) {
path = ".";
}
return new File(path);
} else if (pathstyle == PathStyle.PROJECT_RELATIVE_WITH_LEADING_PROJECT_NAME) {
return new File(this._projectDirectory.getName(), path);
}
// handle ABSOLUTE
return new File(this._projectDirectory, path);
}
/**
* Returns the index of the first file separator.
*
* @param str
* The string that shall be tested.
*
* @return The index of the first file separator or -1.
*/
private int firstFileSeparator(String str) {
int idx1 = str.indexOf('/');
int idx2 = str.indexOf('\\');
if ((idx1 == -1) && (idx2 == -1)) {
return -1;
}
if ((idx1 != -1) && (idx2 != -1)) {
return Math.min(idx1, idx2);
}
return Math.max(idx1, idx2);
}
/**
* Adds the specified nature to the project.
*
* @param nature
* the nature to add.
*/
public void addNature(ProjectNature nature) {
Assure.notNull("nature", nature);
if (!this._natures.contains(nature)) {
this._natures.add(nature);
}
}
/**
* {@inheritDoc}
*/
public boolean hasNature(String natureName) {
Assure.notNull("natureName", natureName);
return hasNature(new ProjectNatureImpl(natureName));
}
/**
* {@inheritDoc}
*/
public boolean hasNature(ProjectNature nature) {
Assure.notNull("nature", nature);
// nature unknown:
if (!this._natures.contains(nature)) {
NatureNicknameRegistry nicknameRegistry = ServiceRegistryAccess.instance().getService(
NatureNicknameRegistry.class);
// try if the user supplied an abbreviation
String abbreviation = nature.getName().toLowerCase();
if (nicknameRegistry.hasNatureForNickname(abbreviation)) {
// check the nature with the full id now
String[] ids = nicknameRegistry.getNaturesForNickname(abbreviation);
for (String id : ids) {
if (hasNature(id)) {
return true;
}
}
}
// there's no mapping so we don't have an abbreviation here
return false;
}
// nature known:
else {
return true;
}
}
/**
* {@inheritDoc}
*/
public ProjectNature[] getNatures() {
return this._natures.toArray(new ProjectNature[this._natures.size()]);
}
/**
* @param referencedProject
*/
public void addReferencedProject(String referencedProject) {
if ((referencedProject != null) && !this._referencedProjects.contains(referencedProject)) {
this._referencedProjects.add(referencedProject);
}
}
/**
* {@inheritDoc}
*/
public String[] getReferencedProjects() {
return this._referencedProjects.toArray(new String[this._referencedProjects.size()]);
}
/**
* Adds the specified role to the EclipseProject.
*
* @param role
* Adds the specified role to the EclipseProject.
*/
public void addRole(ProjectRole role) {
Assure.notNull("role", role);
if (hasRole(role.getClass())) {
throw new RuntimeException("ProjectRole " + role.getClass() + " is already set!");
}
this._roles.add(role);
}
/**
* {@inheritDoc}
*/
public boolean hasRole(Class<? extends ProjectRole> projectRoleClass) {
Assure.notNull("projectRoleClass", projectRoleClass);
Iterator<ProjectRole> iterator = this._roles.iterator();
while (iterator.hasNext()) {
AbstractProjectRole role = (AbstractProjectRole) iterator.next();
if (projectRoleClass.isAssignableFrom(role.getClass())) {
return true;
}
}
return false;
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
public <T extends ProjectRole> T getRole(Class<T> projectRoleClass) {
Assure.notNull("projectRoleClass", projectRoleClass);
Assure.assertTrue(hasRole(projectRoleClass), "hasRole(projectRoleClass) on project '" + getFolderName()
+ "'has to be true for role '" + projectRoleClass + "'!");
Iterator<ProjectRole> iterator = this._roles.iterator();
ProjectRole role = null;
while (iterator.hasNext()) {
role = iterator.next();
if (projectRoleClass.isAssignableFrom(role.getClass())) {
break;
}
}
return (T) role;
}
/**
* {@inheritDoc}
*/
public ProjectRole[] getRoles() {
return this._roles.toArray(new ProjectRole[this._roles.size()]);
}
/**
* Adds the specified build command to the project.
*
* @param command
* the specified build command to the project.
*/
public void addBuildCommand(BuildCommand command) {
Assure.notNull("command", command);
this._buildCommands.add(command);
}
/**
* {@inheritDoc}
*/
public boolean hasBuildCommand(String commandName) {
Assure.notNull("commandName", commandName);
BuildCommand command = new BuildCommandImpl(commandName);
return hasBuildCommand(command);
}
/**
* {@inheritDoc}
*/
public boolean hasBuildCommand(BuildCommand command) {
Assure.notNull("command", command);
return this._buildCommands.contains(command);
}
/**
* {@inheritDoc}
*/
public BuildCommand[] getBuildCommands() {
return this._buildCommands.toArray(new BuildCommand[0]);
}
/**
* Adds a new linked resource to the project.
*
* @param linkedResource
* the linked resource to add.
*/
public void addLinkedResource(LinkedResourceImpl linkedResource) {
Assure.notNull("linkedResource", linkedResource);
if (!this._linkedResources.contains(linkedResource)) {
this._linkedResources.add(linkedResource);
this._linkedResourceNames.add(linkedResource.getName());
}
}
/**
* Returns a specific LinkedResource instance.
*
* @param name
* The name of the desired LinkedResource instance.
*
* @return The desired LinkedResource instance.
*/
public LinkedResourceImpl getLinkedResource(String name) {
Assure.assertTrue(isLinkedResource(name), "Cannot retrieve linked resource '" + name + "' !");
int idx = this._linkedResourceNames.indexOf(name);
return this._linkedResources.get(idx);
}
/**
* Returns true if the supplied name refers to a linked resource.
*
* @param name
* The name of a potential linked resource.
*
* @return true <=> The name applies to a specific linked resource.
*/
public boolean isLinkedResource(String name) {
Assure.notNull("name", name);
return this._linkedResourceNames.contains(name);
}
/**
* {@inheritDoc}
*/
public Workspace getWorkspace() {
return this._workspace;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("[EclipseProject:");
buffer.append(" name: ");
buffer.append(getSpecifiedName());
buffer.append(" folder: ");
buffer.append(getFolder());
buffer.append("]");
return buffer.toString();
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null) {
return false;
}
if (o.getClass() != getClass()) {
return false;
}
EclipseProjectImpl castedObj = (EclipseProjectImpl) o;
if (this._workspace == null) {
if (castedObj._workspace != null) {
return false;
}
} else {
if (!this._workspace.equals(castedObj._workspace)) {
return false;
}
}
if (this._projectDirectory == null) {
if (castedObj._projectDirectory != null) {
return false;
}
} else {
if (!this._projectDirectory.equals(castedObj._projectDirectory)) {
return false;
}
}
if (this._specifiedName == null) {
if (castedObj._specifiedName != null) {
return false;
}
} else {
if (!this._specifiedName.equals(castedObj._specifiedName)) {
return false;
}
}
if (this._comment == null) {
if (castedObj._comment != null) {
return false;
}
} else {
if (!this._comment.equals(castedObj._comment)) {
return false;
}
}
if (this._natures == null) {
if (castedObj._natures != null) {
return false;
}
} else {
if (!this._natures.equals(castedObj._natures)) {
return false;
}
}
if (this._roles == null) {
if (castedObj._roles != null) {
return false;
}
} else {
if (!this._roles.equals(castedObj._roles)) {
return false;
}
}
if (this._buildCommands == null) {
if (castedObj._buildCommands != null) {
return false;
}
} else {
if (!this._buildCommands.equals(castedObj._buildCommands)) {
return false;
}
}
if (this._referencedProjects == null) {
if (castedObj._referencedProjects != null) {
return false;
}
} else {
if (!this._referencedProjects.equals(castedObj._referencedProjects)) {
return false;
}
}
if (this._linkedResources == null) {
return castedObj._linkedResources == null;
} else {
return this._linkedResources.equals(castedObj._linkedResources);
}
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
int hashCode = 1;
hashCode = 31 * hashCode + (this._projectDirectory == null ? 0 : this._projectDirectory.hashCode());
hashCode = 31 * hashCode + (this._specifiedName == null ? 0 : this._specifiedName.hashCode());
hashCode = 31 * hashCode + (this._comment == null ? 0 : this._comment.hashCode());
hashCode = 31 * hashCode + (this._natures == null ? 0 : this._natures.hashCode());
hashCode = 31 * hashCode + (this._roles == null ? 0 : this._roles.hashCode());
hashCode = 31 * hashCode + (this._buildCommands == null ? 0 : this._buildCommands.hashCode());
hashCode = 31 * hashCode + (this._linkedResources == null ? 0 : this._linkedResources.hashCode());
return hashCode;
}
}