package com.sap.furcas.runtime.common.util; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.emf.common.notify.Notifier; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EModelElement; import org.eclipse.emf.ecore.ENamedElement; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.query.index.IndexFactory; import org.eclipse.emf.query.index.query.IndexQueryFactory; import org.eclipse.emf.query.index.query.QueryCommand; import org.eclipse.emf.query.index.query.QueryExecutor; import org.eclipse.emf.query.index.query.ResourceQuery; import org.eclipse.emf.query.index.query.descriptors.ResourceDescriptor; import org.eclipse.emf.query2.Query; import org.eclipse.emf.query2.QueryContext; import org.eclipse.emf.query2.QueryProcessor; import org.eclipse.emf.query2.QueryProcessorFactory; import org.eclipse.emf.query2.ResultSet; import com.sap.furcas.runtime.common.exceptions.MetaModelLookupException; import de.hpi.sam.bp2009.solution.queryContextScopeProvider.impl.ProjectDependencyQueryContextProvider; public class EcoreHelper { /** * Constructs a query context that contains only the given <tt>resources</tt>. */ public static QueryContext getQueryContext(final ResourceSet resourceSet) { return getQueryContext(resourceSet, new HashSet<URI>()); } /** * Constructs a query context that contains the given <tt>resources</tt> as well as all other * resources in the given <tt>resourceSet</tt>. */ public static QueryContext getQueryContext(final ResourceSet resourceSet, final Set<URI> resources) { return new QueryContext() { @Override public URI[] getResourceScope() { Collection<URI> result = new HashSet<URI>(resources); for (Resource resource : resourceSet.getResources()) { result.add(resource.getURI()); } return result.toArray(new URI[result.size()]); } @Override public ResourceSet getResourceSet() { return resourceSet; } }; } /** * Constructs a query context that contains only the given <tt>resources</tt> but no other * resources from the resourceSet or the workspace.<br> * * This is usefull when the exact scope of a query is known. */ public static QueryContext getRestrictedQueryContext(final ResourceSet resourceSet, final Set<URI> resources) { return new QueryContext() { @Override public URI[] getResourceScope() { return resources.toArray(new URI[resources.size()]); } @Override public ResourceSet getResourceSet() { return resourceSet; } }; } /** * Constructs a query context that contains all of <tt>rs</tt>'s resources and all metamodel resources */ public static QueryContext getFullModelUniverseQueryContext(final ResourceSet rs) { return new QueryContext() { @Override public URI[] getResourceScope() { final List<URI> result = new ArrayList<URI>(); IndexFactory.getInstance().executeQueryCommand(new QueryCommand() { @Override public void execute(QueryExecutor queryExecutor) { ResourceQuery<ResourceDescriptor> resourceQuery = IndexQueryFactory.createResourceQuery(); for (ResourceDescriptor desc : queryExecutor.execute(resourceQuery)) { result.add(desc.getURI()); } for (Resource r : rs.getResources()) { result.add(r.getURI()); } } }); return result.toArray(new URI[0]); } @Override public ResourceSet getResourceSet() { return rs; } }; } public static ProjectDependencyQueryContextProvider createProjectDependencyQueryContextProvider(ResourceSet resourceSet, Set<URI> localReferenceScope) { return new ProjectDependencyQueryContextProvider(getAdditionalScopeSeeds(resourceSet, localReferenceScope)); } private static Notifier[] getAdditionalScopeSeeds(ResourceSet resourceSet, Set<URI> referenceScope) { Notifier[] result = new Notifier[referenceScope.size()+1]; int i=0; for (URI uri : referenceScope) { result[i++] = resourceSet.getResource(uri, /* loadOnDemand */ true); } result[i] = resourceSet; return result; } public static EPackage getOutermostPackage(EObject element) { EObject parent = EcoreUtil.getRootContainer(element); if(parent instanceof EPackage) { return (EPackage) parent; } else { return null; } } public static ResultSet executeQuery(String query, QueryContext context) throws MetaModelLookupException { try { QueryProcessor processor = QueryProcessorFactory.getDefault().createQueryProcessor(IndexFactory.getInstance()); ResultSet resultSet = processor.execute(query, context); return resultSet; } catch (RuntimeException rte) { throw new MetaModelLookupException("Exception while making query: " + query + "\n Message :" + rte.getMessage(), rte); } } public static ResultSet executeQuery(Query query, QueryContext context) throws MetaModelLookupException { try { QueryProcessor processor = QueryProcessorFactory.getDefault().createQueryProcessor(IndexFactory.getInstance()); ResultSet resultSet = processor.execute(query, context); return resultSet; } catch (RuntimeException rte) { throw new MetaModelLookupException("Exception while making query: " + query + "\n Message :" + rte.getMessage(), rte); } } public static List<String> getQualifiedName(EClassifier element) { if(element instanceof EModelElement) { List<String> names = new ArrayList<String>(); names.add(element.getName()); EObject parent = element.eContainer(); while(parent != null && parent instanceof ENamedElement) { names.add(((ENamedElement) parent).getName()); parent = parent.eContainer(); } Collections.reverse(names); return names; } return null; } /** * Returns the classifier within the package with the given name. * * This method can also be used to search for sub-parts of the qualified name. For example, * if the full qualified name is Pack::SubPack1::SubPack2::MyClassifier" one can also search for * "SubPack2::MyClassifier" or just "MyClassifier". * */ public static EClassifier findClassifierByName(List<String> qualifiedClassifierName, EPackage pack) { Iterator<EObject> iter = EcoreUtil.getAllContents(pack, /*resolve*/ false); String outmostNamePart = qualifiedClassifierName.get(0); // check if it is a full qualified name for (String subPackName : qualifiedClassifierName) { if(!qualifiedClassifierName.get(qualifiedClassifierName.size() - 1).equals(subPackName)) { if (subPackName.equals(pack.getName())) { return findClassifierByFullQualifiedName(qualifiedClassifierName, pack); } } } // handle non-fully qualified name while (iter.hasNext()) { Object containedObject = iter.next(); if (!(containedObject instanceof ENamedElement)) { continue; } if (!(outmostNamePart.equals(((ENamedElement) containedObject).getName()))) { continue; } if (containedObject instanceof EPackage) { return findClassifierByFullQualifiedName(qualifiedClassifierName, (EPackage) containedObject); } else if (containedObject instanceof EClassifier) { return (EClassifier) containedObject; } else { return null; } } return null; } /** * Returns the the classifier within the package which specified by a full qualified name * such as Pack::SubPack1::SubPack2::MyClassifier" */ public static EClassifier findClassifierByFullQualifiedName(List<String> qualifiedClassifierName, EPackage pack) { for (String namePart : qualifiedClassifierName) { if (namePart.equals(pack.getName())) { continue; } pack.getEClassifier(namePart); EList<EPackage> eSubpackages = pack.getESubpackages(); for (EPackage ePackage : eSubpackages) { if (ePackage.getName().equals(namePart)) { pack = ePackage; continue; } } } return pack.getEClassifier(qualifiedClassifierName.get(qualifiedClassifierName.size() - 1)); } public static boolean isAlive(EObject object) { //TODO how to check whether an object is alive or not in EMF? return object.eResource() != null; } /** * Creates a new resource in the given <tt>resourceSet</tt> named according to the * <tt>nsURI</tt> and postfixed with a generated UUID. */ public static Resource createTransientParsingResource(ResourceSet resourceSet, String nsURI) { Resource resource = resourceSet.createResource(URI.createURI( nsURI + "/transientParsingResource" + EcoreUtil.generateUUID())); // This is a documented hack to consider an empty resource being loaded. See {@link Resource#isLoaded()} resource.getContents().clear(); return resource; } }