package org.bundlemaker.core.analysis;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.apache.tools.ant.types.selectors.SelectorUtils;
import org.bundlemaker.core.analysis.IResourceArtifact.IResourceArtifactContent;
import org.bundlemaker.core.common.utils.FileUtils;
import org.bundlemaker.core.resource.IModule;
import org.bundlemaker.core.resource.IModuleIdentifier;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IPath;
/**
* <p>
* Helper class that provides several static methods useful when working with analysis models.
* </p>
*
* @author Gerd Wütherich (gerd@gerd-wuetherich.de)
*/
public class AnalysisModelQueries {
/**
* <p>
* </p>
*
* @return
*/
public static List<IDependency> getCoreDependencies(Collection<IDependency> dependencies) {
if (dependencies == null) {
return Collections.emptyList();
}
//
final List<IDependency> result = new LinkedList<IDependency>();
for (IDependency dependency : dependencies) {
for (IDependency coreDependency : dependency.getCoreDependencies()) {
result.add(coreDependency);
}
}
return result;
}
/**
* <p>
* </p>
*
* @param artifact
* @param fullyQualifiedName
* @return
*/
public static IBundleMakerArtifact getReferencedArtifact(IBundleMakerArtifact artifact, String fullyQualifiedName) {
//
Assert.isNotNull(artifact);
Assert.isNotNull(fullyQualifiedName);
//
for (IDependency dependency : artifact.getDependenciesTo()) {
if (fullyQualifiedName.equals(dependency.getTo().getQualifiedName())) {
return dependency.getTo();
}
}
//
return null;
}
/**
* <p>
* </p>
*
* @param rootArtifact
* @return
*/
public static IModuleArtifact getModuleArtifact(IRootArtifact rootArtifact, String moduleName) {
//
Assert.isNotNull(rootArtifact);
Assert.isNotNull(moduleName);
//
Collection<IModule> modules = rootArtifact.getModularizedSystem().getModules(moduleName);
if (modules.size() > 1) {
throwException(String.format("Found multiple modules with module name '%s'.", moduleName));
}
//
return modules.size() == 1 ? rootArtifact.getModuleArtifact(modules.toArray(new IModule[0])[0]) : null;
}
/**
* <p>
* </p>
*
* @param rootArtifact
* @param moduleName
* @param version
* @return
*/
public static IModuleArtifact getModuleArtifact(IBundleMakerArtifact rootArtifact, String moduleName, String version) {
//
Assert.isNotNull(rootArtifact);
Assert.isNotNull(moduleName);
Assert.isNotNull(version);
//
IModule module = rootArtifact.getModularizedSystem().getModule(moduleName, version);
//
return module != null ? rootArtifact.getRoot().getModuleArtifact(module) : null;
}
/**
* <p>
* </p>
*
* @param rootArtifact
* @param identifier
* @return
*/
public static IModuleArtifact getModuleArtifact(IRootArtifact rootArtifact, IModuleIdentifier identifier) {
//
Assert.isNotNull(rootArtifact);
Assert.isNotNull(identifier);
//
IModule module = rootArtifact.getModularizedSystem().getModule(identifier);
//
return module != null ? rootArtifact.getModuleArtifact(module) : null;
}
/**
* <p>
* </p>
*
* @param root
* @return
*/
public static IModuleArtifact getJreModuleArtifact(IBundleMakerArtifact root) {
//
IModule jreModule = root.getModularizedSystem().getExecutionEnvironment();
//
return root.getRoot().getModuleArtifact(jreModule);
}
/**
* <p>
* </p>
*
* @param root
* @param moduleIdentifier
* @return
*/
public static IModuleArtifact getMissingTypesModuleArtifact(IBundleMakerArtifact root) {
// create the result array
final IModuleArtifact[] result = new IModuleArtifact[1];
// visit
root.getRoot().accept(new IAnalysisModelVisitor.Adapter() {
@SuppressWarnings("deprecation")
@Override
public boolean visit(IModuleArtifact moduleArtifact) {
//
if (moduleArtifact.isVirtual() && moduleArtifact.getName().equals("<< Missing Types >>")) {
result[0] = moduleArtifact;
}
//
return false;
}
});
// return result
return result[0];
}
/**
* <p>
* </p>
*
* @return
*/
public static Set<IBundleMakerArtifact> getDirectlyReferencedArtifacts(IBundleMakerArtifact artifact) {
//
Set<IBundleMakerArtifact> result = new HashSet<IBundleMakerArtifact>();
//
for (IDependency dependency : artifact.getDependenciesTo()) {
result.add(dependency.getTo());
}
//
return result;
}
/**
* <p>
* </p>
*
* @return
*/
public static List<IBundleMakerArtifact> getReferencingArtifacts(IBundleMakerArtifact artifact) {
//
List<IBundleMakerArtifact> result = new LinkedList<IBundleMakerArtifact>();
//
for (IDependency dependency : artifact.getDependenciesFrom()) {
result.add(dependency.getTo());
}
//
return result;
}
/**
* <p>
* </p>
*
* @return
*/
public static List<IBundleMakerArtifact> getReferencingArtifactsFrom(IBundleMakerArtifact artifact,
IBundleMakerArtifact from) {
//
List<IBundleMakerArtifact> result = new LinkedList<IBundleMakerArtifact>();
//
for (IDependency dependency : artifact.getDependenciesFrom(from)) {
result.add(dependency.getTo());
}
//
return result;
}
/**
* <p>
* </p>
*
* @param artifact
* @return
*/
public static Set<IBundleMakerArtifact> getIndirectlyReferencedArtifacts(IBundleMakerArtifact artifact) {
//
return resolveReferencedArtifacts(artifact, new HashSet<IBundleMakerArtifact>(), true);
}
/**
* <p>
* </p>
*
* @param root
* @param fullyQualifiedName
* @return
*/
public static IGroupArtifact findGroupArtifactByQualifiedName(IBundleMakerArtifact root,
final String fullyQualifiedName) {
// create the result array
final List<IGroupArtifact> result = new LinkedList<IGroupArtifact>();
// visit
root.accept(new IAnalysisModelVisitor.Adapter() {
@Override
public boolean visit(IGroupArtifact groupArtifact) {
//
if (groupArtifact.getQualifiedName().equals(fullyQualifiedName)) {
result.add(groupArtifact);
}
//
return true;
}
});
//
if (result.size() > 1) {
throwException(String.format("Multiple groups with qualified name '%s' exist.", fullyQualifiedName));
}
// return result
return result.size() > 0 ? result.get(0) : null;
}
/**
* <p>
* </p>
*/
public static IResourceArtifact findResourceArtifactByQualifiedName(IBundleMakerArtifact root,
final String fullyQualifiedName) {
// create the result array
final List<IResourceArtifact> result = findResourceArtifactsByQualifiedName(root,
fullyQualifiedName);
//
if (result.size() > 1) {
throwException(String.format("Multiple resources with path name '%s' exist.", fullyQualifiedName));
}
// return result
return result.size() > 0 ? result.get(0) : null;
}
/**
* <p>
* </p>
*
* @param root
* @param fullyQualifiedName
* @return
*/
public static List<IResourceArtifact> findResourceArtifactsByQualifiedName(IBundleMakerArtifact root,
final String fullyQualifiedName) {
// create the result array
final List<IResourceArtifact> result = new LinkedList<IResourceArtifact>();
// visit
root.accept(new IAnalysisModelVisitor.Adapter() {
@Override
public boolean visit(IResourceArtifact resourceArtifact) {
//
if (resourceArtifact.getQualifiedName().equals(fullyQualifiedName)) {
result.add(resourceArtifact);
}
//
return true;
}
});
// return result
return result;
}
/**
* <p>
* </p>
*
* @param root
* @param name
* @return
*/
public static IPackageArtifact findPackageArtifactByQualifiedName(IBundleMakerArtifact root,
final String fullyQualifiedName) {
// create the result array
final List<IPackageArtifact> result = findPackageArtifactsByQualifiedName(root, fullyQualifiedName);
//
if (result.size() > 1) {
throwException(String.format("Multiple packages with name '%s' exist.", fullyQualifiedName));
} else if (result.size() == 0) {
return null;
}
// return result
return result.get(0);
}
/**
* <p>
* </p>
*
* @param root
* @param fullyQualifiedName
* @return
*/
public static List<IPackageArtifact> findPackageArtifactsByQualifiedName(IBundleMakerArtifact root,
final String fullyQualifiedName) {
// create the result array
final List<IPackageArtifact> result = new LinkedList<IPackageArtifact>();
// visit
root.accept(new IAnalysisModelVisitor.Adapter() {
@Override
public boolean visit(IPackageArtifact packageArtifact) {
//
if (packageArtifact.getQualifiedName().equals(fullyQualifiedName)) {
result.add(packageArtifact);
}
//
return true;
}
});
// return result
return result;
}
public static List<IPackageArtifact> findPackageArtifacts(IBundleMakerArtifact root,
final Matcher<IPackageArtifact> matcher) {
// create the result array
final List<IPackageArtifact> result = new LinkedList<IPackageArtifact>();
// visit
root.accept(new IAnalysisModelVisitor.Adapter() {
@Override
public boolean visit(IPackageArtifact packageArtifact) {
//
if (matcher.matches(packageArtifact)) {
result.add(packageArtifact);
}
//
return true;
}
});
// return result
return result;
}
// /**
// * <p>
// * </p>
// *
// * @param root
// * @param fullyQualifiedName
// * @return
// */
// public static List<IPackageArtifact> findPackageArtifactsByQualifiedName(IBundleMakerArtifact root,
// final String fullyQualifiedName, boolean include subpackages) {
//
// // create the result array
// final List<IPackageArtifact> result = new LinkedList<IPackageArtifact>();
//
// // visit
// root.accept(new IAnalysisModelVisitor.Adapter() {
// @Override
// public boolean visit(IPackageArtifact packageArtifact) {
//
// //
// if (packageArtifact.getQualifiedName().equals(fullyQualifiedName)) {
// result.add(packageArtifact);
// }
//
// //
// return true;
// }
// });
//
// // return result
// return result;
// }
/**
* <p>
* </p>
*
* @param clazz
* @param root
* @param fullyQualifiedName
*
* @return
*/
public static <T extends IBundleMakerArtifact> List<T> findArtifactsByQualifiedName(Class<T> clazz,
IBundleMakerArtifact root, final String fullyQualifiedName) {
// create the result array
final List<T> result = new LinkedList<T>();
// visit
root.accept(new GenericAnalysisModelVisitor<T>(clazz) {
@Override
protected void onHandle(T t) {
if (t.getQualifiedName().equals(fullyQualifiedName)) {
result.add(t);
}
}
});
// return result
return result;
}
/**
* <p>
* </p>
*
* @param artifact
* @param artifacts
* @return
*/
private static Set<IBundleMakerArtifact> resolveReferencedArtifacts(IBundleMakerArtifact artifact,
Set<IBundleMakerArtifact> artifacts, boolean transitive) {
//
Assert.isNotNull(artifact);
Assert.isNotNull(artifacts);
//
for (IDependency dependency : artifact.getDependenciesTo()) {
if (artifacts.add(dependency.getTo()) && transitive) {
resolveReferencedArtifacts(dependency.getTo(), artifacts, transitive);
}
}
//
return artifacts;
}
/**
* <p>
* </p>
*
* @param format
*/
private static void throwException(String format) {
// TODO
throw new RuntimeException(format);
}
/************************************************************************************************************/
/**
* <p>
* </p>
*
* @param <T>
* @param artifact
* @param regexp
* @param clazz
* @return
*/
@SuppressWarnings("unchecked")
public static <T extends IBundleMakerArtifact> T getChildByPath(IBundleMakerArtifact artifact, final IPath path,
final Class<T> clazz) {
//
if (artifact == null) {
return null;
}
Assert.isNotNull(clazz);
if (path.segmentCount() > 1) {
return getChildByPath(artifact.getChild(path.segments()[0]), path.removeFirstSegments(1), clazz);
} else {
//
IBundleMakerArtifact result = artifact.getChild(path.segments()[0]);
//
if (result != null && !(clazz.isAssignableFrom(result.getClass()))) {
throw new RuntimeException();
}
//
return (T) result;
}
}
public static <T extends IBundleMakerArtifact> T findChild(IBundleMakerArtifact artifact, final String regexp,
final Class<T> clazz) {
List<T> children = findSuccessor(artifact, regexp, clazz);
if (children.size() == 0) {
return null;
} else if (children.size() == 1) {
return children.get(0);
} else {
// TODO
throw new RuntimeException();
}
}
/**
* {@inheritDoc}
*/
public static <T extends IBundleMakerArtifact> List<T> findSuccessor(IBundleMakerArtifact artifact,
final String regexp, final Class<T> clazz) {
Assert.isNotNull(regexp);
Assert.isNotNull(clazz);
//
final List<T> result = new LinkedList<T>();
//
IAnalysisModelVisitor visitor = new IAnalysisModelVisitor() {
@Override
public boolean visit(IPackageArtifact artifact) {
check(regexp, clazz, result, artifact);
return true;
}
@Override
public boolean visit(IResourceArtifactContent artifact) {
check(regexp, clazz, result, artifact);
return true;
}
@Override
public boolean visit(IResourceArtifact artifact) {
check(regexp, clazz, result, artifact);
return true;
}
@Override
public boolean visit(IModuleArtifact artifact) {
check(regexp, clazz, result, artifact);
return true;
}
@Override
public boolean visit(IGroupArtifact artifact) {
check(regexp, clazz, result, artifact);
return true;
}
@Override
public boolean visit(IRootArtifact artifact) {
check(regexp, clazz, result, artifact);
return true;
}
private <T> void check(String value, final Class<T> clazz, final List<T> result, IBundleMakerArtifact artifact) {
//
if (!clazz.isAssignableFrom(artifact.getClass())) {
return;
}
//
if (artifact.getQualifiedName().equals(value)) {
result.add((T) artifact);
} else if (artifact.getName().equals(value)) {
result.add((T) artifact);
} else if (artifact instanceof IModuleArtifact && ((IModuleArtifact) artifact).getModuleName().equals(value)) {
result.add((T) artifact);
} else {
String artifactName = artifact.getName();
String artifactQualifiedName = artifact.getQualifiedName();
if (clazz.isAssignableFrom(IPackageArtifact.class) || clazz.isAssignableFrom(IResourceArtifactContent.class)) {
artifactName = artifactName.replace('.', '/');
artifactQualifiedName = artifactQualifiedName.replace('.', '/');
value = value.replace('.', '/');
}
artifactName = FileUtils.normalize(artifactName);
artifactQualifiedName = FileUtils.normalize(artifactQualifiedName);
value = FileUtils.normalize(value);
//
if (SelectorUtils.matchPath(value, artifactName, false)
|| SelectorUtils.matchPath(value, artifactQualifiedName, false))
result.add((T) artifact);
}
}
};
artifact.accept(visitor);
//
return result;
}
/**
* {@inheritDoc}
*/
public static <T extends IBundleMakerArtifact> List<T> findSuccessors(IBundleMakerArtifact artifact,
final Class<T> clazz) {
Assert.isNotNull(clazz);
//
final List<T> result = new LinkedList<T>();
//
IAnalysisModelVisitor visitor = new IAnalysisModelVisitor() {
@Override
public boolean visit(IPackageArtifact artifact) {
check(clazz, result, artifact);
return true;
}
@Override
public boolean visit(IResourceArtifactContent artifact) {
check(clazz, result, artifact);
return true;
}
@Override
public boolean visit(IResourceArtifact artifact) {
check(clazz, result, artifact);
return true;
}
@Override
public boolean visit(IModuleArtifact artifact) {
check(clazz, result, artifact);
return true;
}
@Override
public boolean visit(IGroupArtifact artifact) {
check(clazz, result, artifact);
return true;
}
@Override
public boolean visit(IRootArtifact artifact) {
check(clazz, result, artifact);
return true;
}
private <T> void check(final Class<T> clazz, final List<T> result, IBundleMakerArtifact artifact) {
//
if (!clazz.isAssignableFrom(artifact.getClass())) {
return;
}
//
result.add((T) artifact);
}
};
artifact.accept(visitor);
//
return result;
}
/**
* <p>
* </p>
*
* @param bundleMakerArtifact
* @return
*/
public static Collection<IBundleMakerArtifact> getSelfAndAllChildren(IBundleMakerArtifact bundleMakerArtifact) {
//
final Set<IBundleMakerArtifact> result = new HashSet<IBundleMakerArtifact>();
result.add(bundleMakerArtifact);
//
bundleMakerArtifact.accept(new IAnalysisModelVisitor.Adapter() {
/**
* {@inheritDoc}
*/
@Override
public boolean visit(IResourceArtifact resourceArtifact) {
result.add(resourceArtifact);
return super.visit(resourceArtifact);
}
/**
* {@inheritDoc}
*/
@Override
public boolean visit(IResourceArtifactContent typeArtifact) {
result.add(typeArtifact);
return super.visit(typeArtifact);
}
});
return result;
}
/**
* <p>
* </p>
*
* @param artifact
* @param level
* @param stringBuilder
*/
private static void dumpArtifact(IBundleMakerArtifact artifact, int level, StringBuilder stringBuilder, int limit) {
// limit
if (limit != -1 && level >= limit) {
return;
}
//
for (int i = 0; i < level; i++) {
stringBuilder.append(" ");
}
//
stringBuilder.append(artifact.getClass().getName());
stringBuilder.append(" : ");
stringBuilder.append(artifact.getUniquePathIdentifier());
stringBuilder.append("\n");
List<IBundleMakerArtifact> sorted = new ArrayList<IBundleMakerArtifact>(artifact.getChildren());
Collections.sort(sorted, new Comparator<IBundleMakerArtifact>() {
@Override
public int compare(IBundleMakerArtifact o1, IBundleMakerArtifact o2) {
return o1.getUniquePathIdentifier().compareTo(o2.getUniquePathIdentifier());
}
});
for (IBundleMakerArtifact child : sorted) {
// if (child.getType().equals(ArtifactType.Root) || child.getType().equals(ArtifactType.Group)
// || child.getType().equals(ArtifactType.Module)) {
dumpArtifact(child, level + 1, stringBuilder, limit);
// }
}
}
/**
* <p>
* </p>
*
* @param artifact
*/
public static void dumpArtifact(IBundleMakerArtifact artifact) {
if (artifact == null) {
System.out.println("Artifact is 'null'.");
return;
}
StringBuilder builder = new StringBuilder();
dumpArtifact(artifact, 0, builder, -1);
System.out.println(builder.toString());
}
/**
* <p>
* </p>
*
* @param artifact
*/
public static void dumpArtifact(IBundleMakerArtifact artifact, int limit) {
StringBuilder builder = new StringBuilder();
dumpArtifact(artifact, 0, builder, limit);
System.out.println(builder.toString());
}
/**
* <p>
* </p>
*
* @param artifact
* @return
*/
public static String artifactToString(IBundleMakerArtifact artifact) {
StringBuilder builder = new StringBuilder();
dumpArtifact(artifact, 0, builder, -1);
return builder.toString();
}
public static interface Matcher<T extends IBundleMakerArtifact> {
public boolean matches(T artifact);
}
/**
* <p>
* </p>
*
* @author Gerd Wütherich (gerd@gerd-wuetherich.de)
*/
private static class GenericAnalysisModelVisitor<T> implements IAnalysisModelVisitor {
/** the class object */
private Class<T> _clazz;
/**
* <p>
* Creates a new instance of type {@link GenericAnalysisModelVisitor}.
* </p>
*
* @param clazz
*/
public GenericAnalysisModelVisitor(Class<T> clazz) {
Assert.isNotNull(clazz);
//
_clazz = clazz;
}
/**
* {@inheritDoc}
*/
@Override
public final boolean visit(IPackageArtifact artifact) {
handleNode(artifact);
return true;
}
/**
* {@inheritDoc}
*/
@Override
public final boolean visit(IResourceArtifactContent artifact) {
handleNode(artifact);
return true;
}
/**
* {@inheritDoc}
*/
@Override
public final boolean visit(IResourceArtifact artifact) {
handleNode(artifact);
return true;
}
/**
* {@inheritDoc}
*/
@Override
public final boolean visit(IModuleArtifact artifact) {
handleNode(artifact);
return true;
}
/**
* {@inheritDoc}
*/
@Override
public final boolean visit(IGroupArtifact artifact) {
handleNode(artifact);
return true;
}
/**
* {@inheritDoc}
*/
@Override
public final boolean visit(IRootArtifact artifact) {
handleNode(artifact);
return true;
}
/**
* <p>
* </p>
*
* @param artifact
*/
@SuppressWarnings("unchecked")
private void handleNode(IBundleMakerArtifact artifact) {
if (_clazz.isAssignableFrom(artifact.getClass())) {
onHandle((T) artifact);
}
}
/**
* <p>
* </p>
*
* @param t
*/
protected void onHandle(T t) {
//
}
}
}