/*
* Copyright (c) 2011, IETR/INSA of Rennes
* Copyright (c) 2012, Synflow SAS
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* * Neither the name of the IETR/INSA of Rennes nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
package net.sf.orcc.util.util;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
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.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
/**
* This class contains helper methods for Ecore models.
*
* @author Matthieu Wipliez
* @author Herve Yviquel
*
*/
public class EcoreHelper {
/**
* <p>
* Returns the closest container of given <code>ele</code> with the given
* type, or <code>null</code> if no such container exists. This method has
* been copied from the EcoreUtil2 class of Xtext.
* </p>
*
* <p>
* <b> If possible, you should use EcoreUtil2.getContainerOfType() instead
* of this method.</b>
* </p>
*
* @param <T>
* type parameter
* @param ele
* an object
* @param type
* the type of the container
* @return the container of <code>ele</code> with the given type
*/
public static <T extends EObject> T getContainerOfType(EObject ele,
Class<T> type) {
for (EObject e = ele; e != null; e = e.eContainer())
if (type.isInstance(e))
return type.cast(e);
return null;
}
/**
* Returns the list that contains this object, or <code>null</code>.
*
* @param <T>
* type of the objects contained in the list
* @param <T1>
* type of the object as a specialization of <code>T</code>
* @param eObject
* the object
* @return the list that contains this object, or <code>null</code>
*/
@SuppressWarnings("unchecked")
public static <T extends EObject, T1 extends T> List<T> getContainingList(
T1 eObject) {
EStructuralFeature feature = eObject.eContainingFeature();
if (feature.isMany()) {
Object obj = eObject.eContainer().eGet(feature);
if (obj != null && List.class.isAssignableFrom(obj.getClass())) {
return (List<T>) obj;
}
}
return null;
}
/**
* Loads the resource that corresponds to the given file, and returns the
* first object in its contents. Equivalent to
* <code>getEObject(set, file, 0)</code>.
*
* @param set
* a resource set
* @param file
* a file whose extension is registered within EMF
* @return the EObject serialized in the given file
*/
public static <T extends EObject> T getEObject(ResourceSet set, IFile file) {
return getEObject(set, file, 0);
}
/**
* Loads the resource that corresponds to the given file, and returns the
* object in its contents at the given index, or <code>null</code>.
*
* @param set
* a resource set
* @param file
* a file whose extension is registered within EMF
* @param index
* of the object to retrieve
* @return an EObject, or <code>null</code>
*/
public static <T extends EObject> T getEObject(ResourceSet set, IFile file,
int index) {
Resource resource = getResource(set, file);
if (resource == null) {
return null;
}
EList<EObject> contents = resource.getContents();
if (index >= contents.size()) {
return null;
}
@SuppressWarnings("unchecked")
T eObject = (T) contents.get(index);
return eObject;
}
/**
* Finds the feature of the given object that has the given name, and
* returns its value in the given object.
*
* @param eObject
* an EObject
* @param name
* name of a feature of the object's class
*/
@SuppressWarnings("unchecked")
public static <T> T getFeature(EObject eObject, String name) {
EClass eClass = eObject.eClass();
EStructuralFeature feature = eClass.getEStructuralFeature(name);
return (T) eObject.eGet(feature);
}
public static IFile getFile(EObject eObject) {
Resource resource = eObject.eResource();
if (resource == null) {
return null;
}
return getFile(resource);
}
/**
* Returns the IFile associated with the given resource.
*
* @param resource
* a resource
*/
public static IFile getFile(Resource resource) {
String fullPath = resource.getURI().toPlatformString(true);
IPath path = new Path(fullPath);
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
return root.getFile(path);
}
/**
* Finds the feature of the given object that has the given name, and
* returns its value as a list.
*
* @param eObject
* an EObject
* @param name
* name of a feature of the object's class
*/
@SuppressWarnings("unchecked")
public static <T> List<T> getList(EObject eObject, String name) {
EClass eClass = eObject.eClass();
EStructuralFeature feature = eClass.getEStructuralFeature(name);
return (List<T>) eObject.eGet(feature);
}
/**
* Returns an Iterable that contains an iterator that filters descendants of
* the given object that match the given class (or one of its subclasses).
* The iterator does not explore the descendants of the objects of the given
* class (in other words, the underlying iterator is pruned everytime a
* candidate is found): if O of type T contain objects O1 and O2 both with
* the type T, only O will be returned, not O1 nor O2.
*
* @param eObject
* an object
* @param cls
* class of the descendants to match
* @return an Iterable
*/
public static <T> Iterable<T> getObjects(EObject eObject, final Class<T> cls) {
final TreeIterator<EObject> it = eObject.eAllContents();
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private EObject nextObject;
@Override
public boolean hasNext() {
while (it.hasNext()) {
EObject next = it.next();
if (cls.isAssignableFrom(next.getClass())) {
// prune after next
it.prune();
nextObject = next;
return true;
}
}
return false;
}
@Override
@SuppressWarnings("unchecked")
public T next() {
return (T) nextObject;
}
@Override
public void remove() {
it.remove();
}
};
}
};
}
/**
* Returns the EMF resource in the given resource set that corresponds to
* the given file. If the resource does not exist, this method will load it.
*
* @param set
* a resource set
* @param file
* an IFile
* @return a Resource, or <code>null</code>
*/
public static Resource getResource(ResourceSet set, IFile file) {
String pathName = file.getFullPath().toString();
URI uri = URI.createPlatformResourceURI(pathName, true);
try {
return set.getResource(uri, true);
} catch (RuntimeException e) {
}
return null;
}
/**
* Finds the feature of the given object that has the given name, and sets
* its value in the given object to the given value.
*
* @param eObject
* an EObject
* @param name
* name of a feature of the object's class
* @param value
* value that should be set
*/
public static void setFeature(EObject eObject, String name, Object value) {
EClass eClass = eObject.eClass();
EStructuralFeature feature = eClass.getEStructuralFeature(name);
eObject.eSet(feature, value);
}
}