com.synflow.models.util.EcoreHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.synflow.models.util.EcoreHelper.java

Source

/*******************************************************************************
 * 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;
    }

}