blob: 4c8cb65500006602de7573538af5529950dcb37a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2007 Obeo.
* 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:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.emf.compare.util;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.compare.EMFComparePlugin;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcoreFactory;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.EcorePackageImpl;
import org.eclipse.emf.ecore.util.Diagnostician;
/**
* This contains general utility methods for ecore browsing support.
*
* @author Cedric Brun <a href="mailto:cedric.brun@obeo.fr">cedric.brun@obeo.fr</a>
*/
public final class ETools {
private static final String SEPARATOR = "."; //$NON-NLS-1$
private ETools() {
// prevents instantiation
}
/**
* Returns a URI for the eObject, i.e., either the eProxyURI, the URI of the eResource with the fragment
* produced by the eResource, or the URI consisting of just the fragment that would be produced by a
* default Resource with the eObject as its only contents.
*
* @param eObject
* The object for which to get the URI.
* @return The URI for the object.
*/
public static String getURI(EObject eObject) {
EObject object = eObject;
if (object.eResource() != null)
return object.eResource().getURIFragment(object);
// inspired from EMF sources
final StringBuffer result = new StringBuffer("//"); //$NON-NLS-1$
final List<String> uriFragmentPath = new ArrayList<String>();
for (EObject container = object.eContainer(); container != null; container = object.eContainer()) {
uriFragmentPath.add(((InternalEObject)container).eURIFragmentSegment(object
.eContainmentFeature(), object));
object = container;
}
final int size = uriFragmentPath.size();
if (size > 0) {
for (int i = size - 1;; --i) {
result.append(uriFragmentPath.get(i));
if (i == 0)
break;
result.append('/');
}
}
return result.toString();
}
/**
* Validates the given EMF object.
* <p>
* An error is put in the log if the validation failed.
* <p>
* <ul>
* <li><code>!blocker</code> || {@link Diagnostic#OK} => <code>root</code></li>
* <li><code>blocker</code> && !{@link Diagnostic#OK} => <code>null</code></li>
* <li><code>root</code> == <code>null</code> => <code>null</code></li>
* </ul>
*
* @param root
* The object to validate.
* @param blocker
* Indicates if the result must be {@link Diagnostic#OK}.
* @param message
* The error message to put in the log.
* @return The given object or <code>null</code>.
*/
public static EObject validate(EObject root, boolean blocker, String message) {
if (root != null && !(root.getClass().getName().startsWith("org.eclipse.uml2"))) { //$NON-NLS-1$
if (Diagnostician.INSTANCE.validate(root).getSeverity() != Diagnostic.OK) {
EMFComparePlugin.log(message, false);
if (blocker) {
return null;
}
}
}
return root;
}
/**
* Search all the classifiers recursively in a package.
*
* @param ePackage
* The package from which we need the classifiers.
* @return Array of classifiers.
*/
@SuppressWarnings("unchecked")
public static EClassifier[] computeAllClassifiers(EPackage ePackage) {
final List classifiers = computeAllClassifiersList(ePackage);
return (EClassifier[])classifiers.toArray(new EClassifier[] {});
}
/**
* Search all the classifiers recursively in a package.
*
* @param ePackage
* The package from which we need the classifiers.
* @return List of all the package's classifiers.
*/
public static List computeAllClassifiersList(EPackage ePackage) {
return computeAllClassifiersList(ePackage, false);
}
/**
* Search all the classifiers recursively in a package.
*
* @param ePackage
* The package from which we need the classifiers.
* @param classOnly
* Indicates that only the classes are kept.
* @return List of classifiers.
*/
public static List computeAllClassifiersList(EPackage ePackage, boolean classOnly) {
final List classifiers = new BasicEList();
if (ePackage != null)
computeAllClassifiersList(ePackage, classifiers, classOnly);
return classifiers;
}
@SuppressWarnings("unchecked")
private static void computeAllClassifiersList(EPackage ePackage, List all, boolean classOnly) {
final Iterator classifiers = ePackage.getEClassifiers().iterator();
while (classifiers.hasNext()) {
final EClassifier classifier = (EClassifier)classifiers.next();
if (!classOnly) {
all.add(classifier);
} else {
if (classifier instanceof EClass && !((EClass)classifier).isAbstract()
&& !((EClass)classifier).isInterface()) {
all.add(classifier);
}
}
}
final Iterator packages = ePackage.getESubpackages().iterator();
while (packages.hasNext()) {
computeAllClassifiersList((EPackage)packages.next(), all, classOnly);
}
}
/**
* Search a classifier recursively in a package.
* <p>
* Remarks :
* <ul>
* <li>Never returns classifier java.resources.Folder if name = "File"</li>
* <li>Never returns classifier java.resources.Folder if name = "older"</li>
* <li>Returns classifier java.resources.Folder for "Folder" or "resources.Folder"</li>
* </ul>
*
* @param ePackage
* The package from where we seek the given classifier.
* @param classifierName
* The classifier identifier.
* @return The classifier or <code>null</code> if it cannot be found.
*/
public static EClassifier getEClassifier(EPackage ePackage, String classifierName) {
final String name = classifierName.trim();
EClassifier get = null;
final Iterator classifiers = ePackage.getEClassifiers().iterator();
while (get == null && classifiers.hasNext()) {
final EClassifier classifier = (EClassifier)classifiers.next();
final String instanceClassName = SEPARATOR + getEClassifierPath(classifier);
final String endsWith = SEPARATOR + name;
if (instanceClassName.endsWith(endsWith)) {
get = classifier;
}
}
final Iterator packages = ePackage.getESubpackages().iterator();
while (get == null && packages.hasNext()) {
final EClassifier classifier = getEClassifier((EPackage)packages.next(), name);
if (classifier != null)
get = classifier;
}
return get;
}
/**
* Returns the feature <code>name</code> from the given {@link EClassifier}.
*
* @param currentEClassifier
* The classifier to get the feature <code>name</code> from.
* @param name
* Name of the feature we seek.
* @return The feature resolved with the given name.
*/
public static EStructuralFeature getEStructuralFeature(EClassifier currentEClassifier, String name) {
if (currentEClassifier != null && currentEClassifier instanceof EClass)
return getEStructuralFeature((EClass)currentEClassifier, name);
return null;
}
/**
* Returns the feature <code>name</code> from the given {@link EClass}.
*
* @param currentEClass
* The class to get the feature <code>name</code> from.
* @param featureName
* Name of the feature we seek.
* @return The feature resolved with the given name.
*/
public static EStructuralFeature getEStructuralFeature(EClass currentEClass, String featureName) {
final String name = featureName.trim();
if (currentEClass != null)
return currentEClass.getEStructuralFeature(name);
return null;
}
/**
* Returns a factory name for a classifier. There is a factory by package. The factory is used to create
* instances of classifiers.
* <p>
* Sample : "ResourcesFactory" is the name of the factory java.resources.ResourcesFactory
*
* @param eClassifier
* The classifier from which we need the factory's name.
* @return The factory name.
*/
public static String getEClassifierFactoryName(EClassifier eClassifier) {
return getEClassifierFactoryShortName(eClassifier) + "Factory"; //$NON-NLS-1$
}
/**
* Returns a factory short name for a classifier. There is a factory by package. The factory is used to
* create instances of classifiers.
* <p>
* Sample : "Resources" is the short name of the factory java.resources.ResourcesFactory
*
* @param eClassifier
* The classifier from which we need the factory's short name.
* @return The factory short name.
*/
public static String getEClassifierFactoryShortName(EClassifier eClassifier) {
if (eClassifier != null) {
final EPackage p = eClassifier.getEPackage();
final String name = p.getName();
if (name != null && name.length() > 0) {
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
}
return new String();
}
/**
* Returns the full path of the classifier.
* <p>
* Sample : "java.resources.JavaFile" is the full path for the classifier java.resources.JavaFile
*
* @param eClassifier
* The classifier we need the full path of.
* @return The full path of <code>eClassifier</code>.
*/
public static String getEClassifierPath(EClassifier eClassifier) {
String fullPath = null;
if (eClassifier != null) {
final String instanceClassName = eClassifier.getInstanceClassName();
String name = eClassifier.getName();
if (eClassifier.getEPackage() != null) {
EPackage container = eClassifier.getEPackage();
if (container != null && instanceClassName != null
&& instanceClassName.endsWith(container.getName() + SEPARATOR + name)) {
fullPath = instanceClassName;
} else {
while (container != null) {
name = container.getName() + SEPARATOR + name;
container = container.getESuperPackage();
}
fullPath = name;
}
}
}
return fullPath;
}
/**
* Returns the short path of the classifier.
* <p>
* Sample : "resources.JavaFile" is the short path for the classifier java.resources.JavaFile
*
* @param eClassifier
* The classifier we need the short path of.
* @return Short path of <code>eClassifier</code>.
*/
public static String getEClassifierShortPath(EClassifier eClassifier) {
String name = eClassifier.getName();
if (eClassifier.getEPackage() != null)
name = eClassifier.getEPackage().getName() + SEPARATOR + name;
return name;
}
/**
* Creates a package and his children in an ecore model. The children are separated by '.'
* <p>
* Sample : "a.b.c" is a package full path,
* <p>
* "a", "b", and "c" packages are created, the root package "a" is returned.
*
* @param path
* The package full path.
* @return The root package.
*/
@SuppressWarnings("unchecked")
public static EPackage createPackageHierarchy(String path) {
EPackage ePackage = null;
if (path != null && path.length() > 0) {
final EcorePackage p = EcorePackageImpl.init();
final EcoreFactory factory = p.getEcoreFactory();
EPackage parent = null;
final StringTokenizer st = new StringTokenizer(path, SEPARATOR);
while (st.hasMoreTokens()) {
final String name = st.nextToken();
final EPackage child = factory.createEPackage();
child.setName(name);
if (parent != null)
parent.getESubpackages().add(child);
else
ePackage = child;
parent = child;
}
}
return ePackage;
}
/**
* Gets a package in a parent package.
* <p>
* Sample : "a.b" is a parent package and "c.d" is a relative path,
* <p>
* "a.b.c.d" package is returned.
*
* @param parent
* The parent package.
* @param path
* Relative path of the desired package.
* @return The desired package, <code>null</code> if it cannot be found.
*/
public static EPackage getEPackage(EPackage parent, String path) {
EPackage ePackage = parent;
if (path != null && path.length() > 0) {
final StringTokenizer st = new StringTokenizer(path, SEPARATOR);
while (st.hasMoreTokens()) {
final String name = st.nextToken();
boolean found = false;
final Iterator subPackages = ePackage.getESubpackages().iterator();
while (!found && subPackages.hasNext()) {
final EPackage subPackage = (EPackage)subPackages.next();
if (subPackage.getName().equals(name)) {
found = true;
ePackage = subPackage;
}
}
if (!found)
return null;
}
}
return ePackage;
}
/**
* Indicates if an instance of the classifier is an instance of the type.
*
* @param classifier
* Classifier to test against the instances of <code>type</code>.
* @param type
* Type to test.
* @return <code>True</code> if an instance of the classifier is an instance of the type,
* <code>False</code> otherwise.
*/
public static boolean ofType(EClassifier classifier, String type) {
if (classifier instanceof EClass)
return ofType((EClass)classifier, type);
return ofClass(classifier, type);
}
/**
* Indicates if an instance of the class is an instance of the type.
*
* @param eClass
* Class to test agaisnt <code>type</code>.
* @param type
* Name of the type to test.
* @return <code>True</code> if an instance of the class is an instance of the type, <code>False</code>
* otherwise.
*/
public static boolean ofType(EClass eClass, String type) {
boolean isOfType = false;
if (ofClass(eClass, type))
isOfType = true;
final Iterator superTypes = eClass.getESuperTypes().iterator();
while (superTypes.hasNext() && !isOfType) {
final EClassifier superType = (EClassifier)superTypes.next();
if (ofType(superType, type))
isOfType = true;
}
return isOfType;
}
/**
* Indicates if the type corresponds to the name of the classifier.
*
* @param classifier
* The classifier to test.
* @param type
* Type to test against <code>classifier</code> name.
* @return <code>True</code> if the type corresponds to the name of the classifier, <code>False</code>
* otherwise.
*/
public static boolean ofClass(EClassifier classifier, String type) {
final String path = ETools.getEClassifierPath(classifier);
return (SEPARATOR + path).endsWith(SEPARATOR + type);
}
}