/**********************************************************************
* 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.ant.platform;
import org.ant4eclipse.ant.platform.core.SubElementAndAttributesComponent;
import org.ant4eclipse.ant.platform.core.delegate.SubElementAndAttributesDelegate;
import org.ant4eclipse.ant.platform.core.task.AbstractProjectBasedTask;
import org.ant4eclipse.lib.core.service.ServiceRegistryAccess;
import org.ant4eclipse.lib.core.util.Utilities;
import org.ant4eclipse.lib.platform.model.resource.EclipseProject;
import org.ant4eclipse.lib.platform.tools.ReferencedProjectsResolverService;
import org.apache.tools.ant.BuildException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* <p>
* Returns all referenced projects of a specified project
* </p>
*
* @author Nils Hartmann (nils@nilshartmann.net)
* @author Daniel Kasmeroglu (Daniel.Kasmeroglu@Kasisoft.net)
*/
public class GetUsedProjectsTask extends AbstractProjectBasedTask implements SubElementAndAttributesComponent {
/** the default seperator */
private final static String DEFAULT_SEPARATOR = ",";
/**
* The name of an ant property that will hold the list of referenced projects
*/
private String _property;
/**
* An (optional) specified separator that is used to separate the project names (defaults to <b>
* {@link #DEFAULT_SEPARATOR}</b>)
*/
private String _separator;
/**
* Allows to enable self inclusion of the used project if set to <code>true</code>.
*/
private boolean _selfinclude;
/**
* The reference type that is used for the resolving process of projects. A value of <code>null</code> means that all
* reference types are being tried.
*/
private String[] _referencetypes;
/**
*
*/
private SubElementAndAttributesDelegate _subElementAndAttributesDelegate;
public GetUsedProjectsTask() {
this._subElementAndAttributesDelegate = new SubElementAndAttributesDelegate(this);
this._referencetypes = null;
this._selfinclude = false;
}
/**
* Changes the reference type used to influence the project resolving process.
*
* @param newreferencetype
* A reference type which depends on the current configuration of a4e.
*/
public void setReferencetypes(String newreferencetypes) {
String[] elements = null;
if (newreferencetypes != null) {
elements = newreferencetypes.split(",");
}
this._referencetypes = Utilities.cleanup(elements);
}
/**
* <p>
* Sets the name of an ant property that will hold the list of referenced projects.
* </p>
*
* @param property
* the name of an ant property that will hold the list of referenced projects.
*/
public void setProperty(String property) {
this._property = Utilities.cleanup(property);
}
/**
* <p>
* Sets an (optional) separator that is used to separate the project names.
* </p>
*
* @param separator
* an (optional) separator that is used to separate the project names.
*/
public void setSeparator(String separator) {
this._separator = Utilities.cleanup(separator);
}
/**
* <p>
* Enables/disables self inclusion of the current project.
* </p>
*
* @param selfinclude
* <code>true</code> <=> Enable self inclusion.
*/
public void setSelfinclude(boolean selfinclude) {
this._selfinclude = selfinclude;
}
/**
* {@inheritDoc}
*/
public Object createDynamicElement(String name) throws BuildException {
return this._subElementAndAttributesDelegate.createDynamicElement(name);
}
/**
* {@inheritDoc}
*/
public List<Object> getSubElements() {
return this._subElementAndAttributesDelegate.getSubElements();
}
/**
* {@inheritDoc}
*/
public Map<String, String> getSubAttributes() {
return this._subElementAndAttributesDelegate.getSubAttributes();
}
/**
* {@inheritDoc}
*/
public void setDynamicAttribute(String name, String value) throws BuildException {
this._subElementAndAttributesDelegate.setDynamicAttribute(name, value);
}
/**
* {@inheritDoc}
*/
@Override
protected void preconditions() throws BuildException {
super.preconditions();
if (this._property == null) {
throw new BuildException("The attribute 'property' has not been set or is empty.");
}
/**
* @todo [09-Jul-2009:KASI] Checking of parental classes should not be splitted up into multiple methods. This
* should happen within the parental {@link #preconditions()} method. The use of these splitted checks is no
* longer necessary since we've introduced the delegates providing the splitted checks, so the tasks
* themselves don't need to behave the same way.
*/
requireWorkspaceAndProjectNameSet();
if (this._referencetypes != null) {
// check if we can use the provided reference type
String[] allowed = getResolver().getReferenceTypes();
for (String reftype : this._referencetypes) {
if (!Utilities.contains(reftype, allowed)) {
throw new BuildException("The 'referencetypes' value '" + reftype + "' is not supported.");
}
}
}
}
/**
* {@inheritDoc}
*/
@Override
protected void doExecute() {
if (this._separator == null) {
this._separator = DEFAULT_SEPARATOR;
}
String[] types = getResolver().getReferenceTypes();
if (this._referencetypes != null) {
// there's a restriction provided by the user
types = this._referencetypes;
}
EclipseProject project = getEclipseProject();
List<EclipseProject> referenced = new ArrayList<EclipseProject>();
// load the directly referenced projects
referenced.addAll(getResolver().resolveReferencedProjects(project, types, getSubElements()));
if (this._selfinclude) {
// include ourselves as requested
referenced.add(0, project);
}
// generate the result value
StringBuffer buffer = new StringBuffer();
if (!referenced.isEmpty()) {
buffer.append(referenced.get(0).getSpecifiedName());
for (int i = 1; i < referenced.size(); i++) {
buffer.append(this._separator);
buffer.append(referenced.get(i).getSpecifiedName());
}
}
getProject().setProperty(this._property, buffer.toString());
}
/**
* Returns the currently registered resolver service.
*
* @return The currently registered resolver service. Not <code>null</code>.
*/
private ReferencedProjectsResolverService getResolver() {
/**
* @todo [09-Jul-2009:KASI] The inner convenience classes located in service interfaces should be removed. I'm just
* using this shortcut here in order to support refactoring in future.
*/
return ServiceRegistryAccess.instance().getService(ReferencedProjectsResolverService.class);
}
} /* ENDCLASS */