blob: de34bf75e2fbed50d2dba981ef76cec7e0c52da5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2010 Mia-Software.
* 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:
* Nicolas Bros (Mia-Software) - initial API and implementation
*******************************************************************************/
package org.eclipse.gmt.modisco.infra.browser.uicore.internal.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.gmt.modisco.infra.browser.uicore.internal.Activator;
import org.eclipse.gmt.modisco.infra.common.core.internal.utils.ModelUtils;
import org.eclipse.gmt.modisco.infra.common.core.logging.MoDiscoLogger;
/**
* Utility functions related to EMF
* @deprecated Will be replaced by EMF Facet,
* cf https://bugs.eclipse.org/bugs/show_bug.cgi?id=470715
*/
@Deprecated
public class EMFUtil {
/**
* @return whether the given EObject is in the first resource of its resource set
*/
public static boolean isInFirstResource(final EObject eObject) {
final Resource resource = eObject.eResource();
if (resource == null) {
return false;
}
final ResourceSet resourceSet = resource.getResourceSet();
if (resourceSet == null) {
return false;
}
final EList<Resource> resources = resourceSet.getResources();
if (resources.size() > 0) {
if (resourceSet.getResources().get(0) == resource) {
return true;
}
}
return false;
}
/**
* Search for instances of the given EClass
*
* @param eClass
* the EClass of the elements that are looked for
* @param resource
* the resource to search in
* @return elements that are instances of the given EClass
*/
public Collection<EObject> findInstancesOf(final EClass eClass, final Resource resource) {
final ArrayList<EObject> instances = new ArrayList<EObject>();
final TreeIterator<EObject> allContents = resource.getAllContents();
while (allContents.hasNext()) {
final EObject eObject = allContents.next();
if (eObject.eClass() == eClass) {
instances.add(eObject);
}
}
return instances;
}
/**
* Find and return all the metaclasses of the given resource set.
*
* @return a list of all the metaclasses of elements contained in the resource set, and
* metaclasses in resources in which metaclasses of elements in the resource set have
* been found
*/
public static synchronized Collection<EClass> findAllClasses(
final Collection<Resource> browsedResources) {
// TODO: try to read from PackageRegistry?
// resourceSet.getPackageRegistry().keySet()
// TODO: find EClasses in EPackages
/*
* the list of metaclasses is a tree set so that it is always sorted and each class is
* guaranteed to appear at most once.
*/
final TreeSet<EClass> classes = new TreeSet<EClass>(new Comparator<EClass>() {
public int compare(final EClass c1, final EClass c2) {
return ModelUtils.getMetaclassQualifiedName(c1).compareTo(
ModelUtils.getMetaclassQualifiedName(c2));
}
});
/** The resources, in a HashSet to get constant time access */
final HashSet<Resource> resources = new HashSet<Resource>();
/**
* Resources that were discovered outside of the resource set, and which contain metaclasses
* used in the model
*/
final ArrayList<Resource> newResources = new ArrayList<Resource>();
resources.addAll(browsedResources);
for (final Resource resource : browsedResources) {
if (resource == null) {
MoDiscoLogger.logWarning(
"null Resource in browsed resources", Activator.getDefault()); //$NON-NLS-1$
continue;
}
Object mutex = resource.getResourceSet();
if (mutex == null) {
mutex = EMFUtil.class;
}
synchronized (mutex) {
synchronized (resource) {
final TreeIterator<EObject> allContents = EcoreUtil.getAllContents(resource,
false);
while (allContents.hasNext()) {
final EObject eObject = allContents.next();
if (eObject instanceof EClass) {
final EClass eClass = (EClass) eObject;
classes.add(eClass);
} else {
// EPackage ePackage =
// eObject.eClass().getEPackage();
// System.out.println("package : " +
// ePackage.getNsURI());
final EClass eClass = eObject.eClass();
if (eClass != null) {
// make sure all model elements have their
// metaclass
// in the list
classes.add(eClass);
// if we discovered a new resource, then
// memorize it
final Resource res = eClass.eResource();
if (res != null && !resources.contains(res)) {
resources.add(res);
newResources.add(res);
}
}
}
}
}
}
}
/*
* Now, add the classes that reside in resources that we discovered and are not part of the
* resource set. For example, the UML models have metaclasses in
* 'http://www.eclipse.org/uml2/2.1.0/UML', which is not in the resource set.
*/
addAll(classes, newResources);
newResources.clear();
final ArrayList<EClass> newClasses = new ArrayList<EClass>();
for (final EClass eClass : classes) {
final EList<EClass> allSuperTypes = eClass.getEAllSuperTypes();
for (final EClass superclass : allSuperTypes) {
newClasses.add(superclass);
// if we discovered a new resource, then memorize it
final Resource resource = superclass.eResource();
if (resource != null && !resources.contains(resource)) {
resources.add(resource);
newResources.add(resource);
}
}
}
for (final EClass eClass : newClasses) {
classes.add(eClass);
}
// add classes in newly discovered resources (again)
addAll(classes, newResources);
// for (Resource resource : resources) {
// System.out.println(resource.getURI().toString());
// }
return classes;
}
/**
* Add all the classes in <code>resources</code> to the <code>classes</code> set
*/
private static void addAll(final Set<EClass> classes, final List<Resource> resources) {
for (final Resource resource : resources) {
final TreeIterator<EObject> allContents = resource.getAllContents();
while (allContents.hasNext()) {
final EObject eObject = allContents.next();
if (eObject instanceof EClass) {
final EClass eClass = (EClass) eObject;
classes.add(eClass);
}
}
}
}
/**
* Find the most specific metaclass that is common to all of the given elements.
*
* @return the common metaclass or <code>null</code> if none was found
*/
public static EClass findCommonClass(final List<EObject> elements) {
// FIXME this algorithm can make a choice about a branch early and not
// find
// a solution, when a solution does exist
EClass eClass = null;
for (final EObject element : elements) {
final EClass elementEClass = element.eClass();
if (eClass == null) {
eClass = elementEClass;
} else {
if (eClass.isSuperTypeOf(elementEClass)) {
continue;
} else if (elementEClass.isSuperTypeOf(eClass)) {
eClass = elementEClass;
} else {
// elements are on two different branches
// try to find a common metaclass
eClass = findSuperType(eClass, elementEClass);
if (eClass == null) {
return null;
}
}
}
}
return eClass;
}
/**
* Find the first superclass of <code>eClass</code> that is a superclass of <code>element</code>
*/
private static EClass findSuperType(final EClass eClass, final EClass element) {
// do a breadth-first search (with a bottom-up tree)
final LinkedList<EClass> breadthFirstList = new LinkedList<EClass>();
breadthFirstList.addFirst(eClass);
while (!breadthFirstList.isEmpty()) {
final EClass candidateClass = breadthFirstList.poll();
if (candidateClass.isSuperTypeOf(element)) {
return candidateClass;
}
// add all the direct super-types of this class
for (final EClass supertype : candidateClass.getESuperTypes()) {
breadthFirstList.addLast(supertype);
}
}
return null;
}
/**
* Try to resolve the given proxy.
*
* @return whether the proxy could be resolved
*/
public static boolean tryResolve(final EObject eObject) {
final EObject resolved = EcoreUtil.resolve(eObject, (EObject) null);
return !resolved.eIsProxy();
}
/** @return the proxy URI for the given EObject or an empty String if none */
public static String proxyURI(final EObject eObject) {
final URI eProxyURI = ((InternalEObject) eObject).eProxyURI();
if (eProxyURI == null) {
return ""; //$NON-NLS-1$
}
return eProxyURI.toString();
}
public static <T extends ENamedElement> T findElementWithName(final String name,
final EList<T> elements) {
for (T element : elements) {
if (name.equals(element.getName())) {
return element;
}
}
return null;
}
public static EClass findMetaclassWithName(final String metaclassFullyQualifiedName,
final List<EClass> metaclasses) {
for (EClass eClass : metaclasses) {
if (metaclassFullyQualifiedName.equals(ModelUtils.getMetaclassQualifiedName(eClass))) {
return eClass;
}
}
return null;
}
/**
* @return the name of the package in the package registry with this nsURI, or <code>null</code>
* if not found
*/
public static String getMetamodelName(final String nsURI) {
if (nsURI != null) {
final EPackage ePackage = EPackage.Registry.INSTANCE.getEPackage(nsURI);
if (ePackage != null) {
final String name = ePackage.getName();
if (name != null) {
return name;
}
}
final URI uri = URI.createURI(nsURI);
final String lastSegment = uri.lastSegment();
if (lastSegment != null) {
return lastSegment;
}
}
return null;
}
/** @return the list of {@link EClass}es found in the following resource */
public static List<EClass> getMetaclasses(final Resource metamodel) {
final List<EClass> metaclasses = new ArrayList<EClass>();
final TreeIterator<EObject> allContents = metamodel.getAllContents();
while (allContents.hasNext()) {
final EObject eObject = allContents.next();
if (eObject instanceof EClass) {
final EClass eClass = (EClass) eObject;
metaclasses.add(eClass);
}
}
return metaclasses;
}
/**
* Find the {@link EObject} with the given URI in the given {@link ResourceSet}
*
* @return the element or <code>null</code> if no element was found with this URI in the given
* {@link ResourceSet}
*/
public static EObject findElementByURI(final String uriFragment, final ResourceSet resourceSet) {
EList<Resource> resources = resourceSet.getResources();
for (Resource resource : resources) {
EObject eObject = resource.getEObject(uriFragment);
if (eObject != null) {
return eObject;
}
}
// Resource resource;
// resource.
// TreeIterator<Notifier> allContents = resourceSet.getAllContents();
// while (allContents.hasNext()) {
// Notifier notifier = allContents.next();
// if (notifier instanceof EObject) {
// EObject eObject = (EObject) notifier;
// if (uri.equals(EcoreUtil.getURI(eObject))) {
// return eObject;
// }
// }
// }
return null;
}
}