blob: b5f36f335174ee4a7bc132150c77dfc761ea1341 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2011 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
*
*
*******************************************************************************/
package org.eclipse.gmt.modisco.infra.common.core.internal.utils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAttribute;
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.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 org.eclipse.emf.ecore.util.FeatureMap;
import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.IItemLabelProvider;
/**
* Utility class for models.
*
*/
public final class ModelUtils {
private static ResourceSet resourceSet = new ResourceSetImpl();
private static AdapterFactory composedAdapterFactory = new ComposedAdapterFactory(
ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
/**
* Utility classes don't need to (and shouldn't) be instantiated.
*/
private ModelUtils() {
// prevents instantiation
}
/**
* Loads a model from a {@link java.io.File File} in a given
* {@link ResourceSet}.
*
* @param file
* where the model is stored.
* @return The model loaded from the URI.
* @throws IOException
* If the given file does not exist.
*/
public static Resource loadModel(final File file) throws IOException {
URI modelURI = URI.createFileURI(file.getPath());
return ModelUtils.loadModel(modelURI);
}
/**
* Loads a model from a {@link URI}.
*
* @param modelURI
* the URI of the model.
* @return The model loaded from the URI.
* @throws IOException
* If the model couldn't be loaded.
*/
public static Resource loadModel(final URI modelURI) throws IOException {
String fileExtension = modelURI.fileExtension();
if (fileExtension == null || fileExtension.length() == 0) {
fileExtension = Resource.Factory.Registry.DEFAULT_EXTENSION;
}
final Resource.Factory.Registry reg = Resource.Factory.Registry.INSTANCE;
final Object resourceFactory = reg.getExtensionToFactoryMap().get(fileExtension);
if (resourceFactory != null) {
ModelUtils.resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap()
.put(fileExtension, resourceFactory);
} else {
ModelUtils.resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap()
.put(fileExtension, new XMIResourceFactoryImpl());
}
final Resource result = ModelUtils.resourceSet.createResource(modelURI);
if (result != null) {
result.load(null);
}
return result;
}
private static Set<EObject> getElementsByType(final Resource extent, final String type) {
Set<EObject> ret = new HashSet<EObject>();
for (Iterator<EObject> i = extent.getAllContents(); i.hasNext();) {
EObject eo = i.next();
if (eo.eClass().getName().equals(type)) {
ret.add(eo);
}
}
return ret;
}
/**
* Metamodel register : allows to open/compare specific models.
*
* @param metamodelURI
* the metamodel URI
* @throws IOException
*/
public static void registerMetamodel(final URI metamodelURI) throws IOException {
if (EPackage.Registry.INSTANCE.getEPackage(metamodelURI.toString()) != null) {
return;
}
Resource.Factory myEcoreFactory = new EcoreResourceFactoryImpl();
Resource mmExtent = myEcoreFactory.createResource(metamodelURI);
mmExtent.load(new FileInputStream(metamodelURI.toFileString()), Collections.EMPTY_MAP);
for (EObject eObject : ModelUtils.getElementsByType(mmExtent, "EPackage")) { //$NON-NLS-1$
EPackage p = (EPackage) eObject;
String nsURI = p.getNsURI();
if (nsURI == null) {
nsURI = p.getName();
p.setNsURI(nsURI);
}
EPackage.Registry.INSTANCE.put(nsURI, p);
}
for (EObject eo : ModelUtils.getElementsByType(mmExtent, "EDataType")) { //$NON-NLS-1$
EStructuralFeature sf;
sf = eo.eClass().getEStructuralFeature("name"); //$NON-NLS-1$
String tname = (String) eo.eGet(sf);
String icn = null;
if (tname.equals("Boolean")) { //$NON-NLS-1$
icn = "java.lang.Boolean"; //$NON-NLS-1$
} else if (tname.equals("Double") || tname.equals("Real")) { //$NON-NLS-1$ //$NON-NLS-2$
icn = "java.lang.Double"; //$NON-NLS-1$
} else if (tname.equals("Float")) { //$NON-NLS-1$
icn = "java.lang.Float"; //$NON-NLS-1$
} else if (tname.equals("Integer")) { //$NON-NLS-1$
icn = "java.lang.Integer"; //$NON-NLS-1$
} else if (tname.equals("String")) { //$NON-NLS-1$
icn = "java.lang.String"; //$NON-NLS-1$
}
if (icn != null) {
sf = eo.eClass().getEStructuralFeature("instanceClassName"); //$NON-NLS-1$
eo.eSet(sf, icn);
}
}
}
/**
* Serializes the given EObjet as a String.
*
* @param root
* Root of the objects to be serialized.
* @return The given EObjet serialized as a String.
* @throws IOException
* Thrown if an I/O operation has failed or been interrupted
* during the saving process.
*/
public static String serialize(final EObject root) throws IOException {
if (root == null) {
throw new NullPointerException("ModelUtils.NullSaveRoot"); //$NON-NLS-1$
}
final XMIResourceImpl newResource = new XMIResourceImpl();
final StringWriter writer = new StringWriter();
newResource.getContents().add(root);
newResource.save(writer, Collections.EMPTY_MAP);
return writer.toString();
}
/**
* Returns a name for the given model element from the EMF global registry,
* or use a default name taken from a String attribute.
*
* @return a name for the given element
*/
public static String getName(final EObject eObject) {
IItemLabelProvider itemLabelProvider = (IItemLabelProvider) ModelUtils.composedAdapterFactory
.adapt(eObject, IItemLabelProvider.class);
if (itemLabelProvider != null) {
return itemLabelProvider.getText(eObject);
}
return ModelUtils.getDefaultName(eObject);
}
/**
* @return a default name based on a string feature of the given
* {@link EObject}
*/
public static String getDefaultName(final EObject eObject) {
// find a feature that can be used as a name
final EStructuralFeature feature = ModelUtils.getLabelFeature(eObject.eClass());
if (feature != null) {
final Object value = eObject.eGet(feature);
if (value != null) {
return StringUtils.truncateBeforeNewline(value.toString());
}
}
if (eObject.eIsProxy()) {
return StringUtils.truncateBeforeNewline(EcoreUtil.getURI(eObject).toString());
}
return ""; //$NON-NLS-1$
}
/** Copied from ReflectiveItemProvider class */
private static EStructuralFeature getLabelFeature(final EClass eClass) {
EAttribute result = null;
for (final EAttribute eAttribute : eClass.getEAllAttributes()) {
if (!eAttribute.isMany()
&& eAttribute.getEType().getInstanceClass() != FeatureMap.Entry.class) {
if ("name".equalsIgnoreCase(eAttribute.getName())) { //$NON-NLS-1$
result = eAttribute;
break;
} else if (result == null) {
result = eAttribute;
} else if (eAttribute.getEAttributeType().getInstanceClass() == String.class
&& result.getEAttributeType().getInstanceClass() != String.class) {
result = eAttribute;
}
}
}
return result;
}
/** @return the qualified name of the given metaclass */
public static String getMetaclassQualifiedName(final EClassifier eClass) {
final ArrayList<String> qualifiedNameParts = new ArrayList<String>();
final StringBuilder builder = new StringBuilder();
EPackage ePackage = eClass.getEPackage();
while (ePackage != null) {
qualifiedNameParts.add(ePackage.getName());
ePackage = ePackage.getESuperPackage();
}
for (int i = qualifiedNameParts.size() - 1; i >= 0; i--) {
builder.append(qualifiedNameParts.get(i) + "."); //$NON-NLS-1$
}
builder.append(eClass.getName());
return builder.toString();
}
public static IFile getIFileFormEObject(final EObject eObject) {
URI uri = eObject.eResource().getURI();
return ModelUtils.getIFileFromPlatformURI(uri);
}
public static IFile getIFileFromPlatformURI(final URI uri) {
IFile iFile = null;
if (uri.isPlatformResource()) {
String projectName = uri.segment(1);
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
StringBuilder path = new StringBuilder();
String[] segments = uri.segments();
for (int i = 2; i < segments.length; i++) {
path.append("/").append(segments[i]); //$NON-NLS-1$
}
iFile = project.getFile(path.toString());
}
return iFile;
}
/**
* Compute the resources referenced directly or indirectly from a given
* resource
*
* @param resource
* @param allReferencedResources
* parameter inout which is completed with the referenced
* resources
*/
public static void computeReferencedResources(final Resource resource,
final Set<Resource> allReferencedResources) {
if (resource == null) {
return;
}
final Set<Resource> directReferencedResources = new HashSet<Resource>();
for (EObject root : resource.getContents()) {
Map<EObject, Collection<EStructuralFeature.Setting>> externalReferences = EcoreUtil.ExternalCrossReferencer
.find(root);
if (!externalReferences.isEmpty()) {
for (EObject external : externalReferences.keySet()) {
Resource externalResource;
if (external.eIsProxy()) {
externalResource = EcoreUtil.resolve(external, root).eResource();
} else {
externalResource = external.eResource();
}
if (externalResource != null) {
directReferencedResources.add(externalResource);
}
}
}
}
// recurse on sub-resources
for (Resource directlyReferencedResource : directReferencedResources) {
// avoid infinite recursion in the case of mutually referencing
// resources
if (!allReferencedResources.contains(directlyReferencedResource)) {
allReferencedResources.add(directlyReferencedResource);
computeReferencedResources(directlyReferencedResource, allReferencedResources);
}
}
}
private static class CrossReferencer extends EcoreUtil.CrossReferencer {
private static final long serialVersionUID = 4564174659913803329L;
public CrossReferencer(final Resource resource) {
super(resource);
}
@Override
protected boolean resolve() {
return false;
}
public EcoreUtil.CrossReferencer findReferences() {
crossReference();
done();
return this;
}
}
public static Set<URI> computeReferencedResourcesURIs(final Resource resource) {
if (resource == null) {
return null;
}
final Set<URI> referencedResourceURIs = new HashSet<URI>();
CrossReferencer crossReferencer = new CrossReferencer(resource);
crossReferencer.findReferences();
if (!crossReferencer.isEmpty()) {
for (EObject externalEObject : crossReferencer.keySet()) {
URI uri = EcoreUtil.getURI(externalEObject);
if (uri != null) {
referencedResourceURIs.add(uri.trimFragment());
}
}
}
return referencedResourceURIs;
}
/**
* Computes the packages referenced, directly or indirectly, from the given
* EPackage. "referenced" term covers here inheritance, references composite
* or not.
*
* @param aPackage
* @return
*/
public static Set<EPackage> computeReferencedPackages(final EPackage aPackage) {
Set<Resource> referencedResources = new HashSet<Resource>();
Set<EPackage> referencedPackages = new HashSet<EPackage>();
// assume that EPackages are loaded in separate Resource instances
computeReferencedResources(aPackage.eResource(), referencedResources);
for (Resource aReferencedResource : referencedResources) {
final TreeIterator<EObject> allContents = aReferencedResource.getAllContents();
while (allContents.hasNext()) {
final EObject eObject = allContents.next();
if (eObject instanceof EPackage) {
referencedPackages.add((EPackage) eObject);
}
}
}
return referencedPackages;
}
}