Java tutorial
/******************************************************************************* * Copyright (c) 2012-2015 Synflow SAS. * 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: * Matthieu Wipliez - some modifications *******************************************************************************/ /* * Copyright (c) 2011, IETR/INSA of Rennes * 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 com.synflow.models.util; import java.util.HashMap; 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.TreeIterator; import org.eclipse.emf.common.util.URI; 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; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.util.EcoreUtil; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; /** * This class contains helper methods for Ecore models. * * @author Matthieu Wipliez * @author Herve Yviquel * */ public class EcoreHelper { /** * If eObject is already contained, returns a copy of it. * * @param expression * a Cx expression * @return <code>expression</code> itself, or a copy of it */ public static <T extends EObject> T copyIfNeeded(T eObject) { if (eObject.eContainer() == null) { return eObject; } return EcoreUtil.copy(eObject); } /** * Returns the container of <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. * * @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); return List.class.cast(obj); } return null; } /** * Loads the resource that corresponds to the given file, and returns the first object in its * contents that matches the given class, or <code>null</code> otherwise. * * @param file * a file * @param cls * expected class * @return an object or <code>null</code> */ public static <T extends EObject> T getEObject(IFile file, Class<T> cls) { ResourceSet set = new ResourceSetImpl(); ((ResourceSetImpl) set).setURIResourceMap(new HashMap<URI, Resource>()); return getEObject(set, file, cls); } /** * Loads the resource that corresponds to the given file, and returns the first object in its * contents that matches the given class, or <code>null</code> otherwise. * * @param set * a resource set * @param file * a file whose extension is registered within EMF * @param cls * a class * @return an EObject matching the given class, or <code>null</code> */ public static <T extends EObject> T getEObject(ResourceSet set, IFile file, Class<T> cls) { return Iterables.getFirst(getEObjects(set, file, cls), null); } /** * Loads the resource that corresponds to the given file, and returns the contents that matches * the given class, or <code>null</code> otherwise. * * @param file * a file * @param cls * expected class * @return an iterable of objects (may be empty) */ public static <T extends EObject> Iterable<T> getEObjects(IFile file, Class<T> cls) { ResourceSet set = new ResourceSetImpl(); ((ResourceSetImpl) set).setURIResourceMap(new HashMap<URI, Resource>()); return getEObjects(set, file, cls); } /** * Loads the resource that corresponds to the given file, and returns all objects in its * contents that matches the given class. * * @param set * a resource set * @param file * a file whose extension is registered within EMF * @return a iterable of objects (may be empty) */ public static <T extends EObject> Iterable<T> getEObjects(ResourceSet set, IFile file, Class<T> cls) { String pathName = file.getFullPath().toString(); URI uri = URI.createPlatformResourceURI(pathName, true); try { Resource resource = set.getResource(uri, true); return Iterables.filter(resource.getContents(), cls); } catch (RuntimeException e) { } return ImmutableSet.of(); } 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, or <code>null</code> if the information * is not available (e.g. the resource plugin is not loaded). * * @param resource * a resource */ public static IFile getFile(Resource resource) { if (ResourcesPlugin.getPlugin() == null) { return null; } String fullPath = resource.getURI().toPlatformString(true); IPath path = new Path(fullPath); IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); return root.getFile(path); } /** * 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(); } }; } }; } /** * Creates a new resource set. * * @return a resource set */ public static ResourceSet newResourceSet() { ResourceSetImpl set = new ResourceSetImpl(); set.setURIResourceMap(new HashMap<URI, Resource>()); return set; } }