blob: 6c266f47cfe61e9327aeb5da2f4056c36c384ffb [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2019 The University of York.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
package org.eclipse.epsilon.executors.model.util;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.Resource.Factory;
import org.eclipse.emf.ecore.resource.Resource.Factory.Registry;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.XMLParserPool;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMLParserPoolImpl;
/**
* Set of utility methods for working with EMF models.
* @author Horacio Hoyos Rodriguez
*
*/
public class EmfModelUtil {
private static XMLParserPool parserPool = new XMLParserPoolImpl();
private static Map<Object, Object> emfLoadOptions;
static {
HashMap<Object, Object> aMap = new HashMap<>();
aMap.put(XMLResource.OPTION_DEFER_IDREF_RESOLUTION, true);
aMap.put(XMLResource.OPTION_USE_PARSER_POOL, parserPool);
emfLoadOptions = Collections.unmodifiableMap(aMap);
}
/**
* Register the XMI resource factory locally into a specific ResourceSet. The ResourceSet
* should be created via <code>ResourceSet rs = new ResourceSetImpl();</code>
*
* @param rs the rs
*/
public static void registerXMIFactoryLocally(ResourceSet rs) {
registerResourceFactoryLocally("xmi", new XMIResourceFactoryImpl(), rs);
}
/**
* Register the XMI resource factory globally.
*/
public static void registerXMIFactoryGlobally() {
registerResourceFactoryGlobally("xmi", new XMIResourceFactoryImpl());
}
/**
* Register the Ecore resource factory locally into a specific ResourceSet. The ResourceSet
* should be created via <code>ResourceSet rs = new ResourceSetImpl();</code>
*
* @param rs the rs
*/
public static void registerEcoreFactoryLocally(ResourceSet rs) {
registerResourceFactoryLocally("ecore", new EcoreResourceFactoryImpl(), rs);
}
/**
* Register the Ecore resource factory globally.
*/
public static void registerEcoreFactoryGlobally() {
registerResourceFactoryGlobally("ecore", new EcoreResourceFactoryImpl());
}
/**
* Register the ".model" extension as XMI resources locally into a specific ResourceSet. The
* ResourceSet should be created via <code>ResourceSet rs = new ResourceSetImpl();</code>
*
* @param rs the rs
*/
public static void registerModelExtensionLocally(ResourceSet rs) {
registerResourceFactoryLocally("model", new XMIResourceFactoryImpl(), rs);
}
/**
* Register the ".model" extension as XMI resources globally
*/
public static void registerModelExtensionGlobally() {
registerResourceFactoryGlobally("model", new XMIResourceFactoryImpl());
}
/**
* Register a Factory for a specific extension locally.
*
* @param extension the file extension
* @param factory the factory to handle files with the given extension
* @param rs the resource set where the factory is registered
*/
public static void registerResourceFactoryLocally(String extension, Factory factory, ResourceSet rs) {
rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put(extension, factory);
}
/**
* Register a Factory for a specific extension blobally.
*
* @param extension the file extension
* @param factory the factory to handle files with the given extension
*/
public static void registerResourceFactoryGlobally(String extension, Factory factory) {
Registry registry = Resource.Factory.Registry.INSTANCE;
registry.getExtensionToFactoryMap().put(extension, factory);
}
/** The matcher. */
public static PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:*.ecore");
/**
* Register all the packages found in the given Ecore metamodel locally.
*
* @param location the metamodel location, must be a valid file system path
* @param rs the Resource Set
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void registerEcoreMetamodelLocally(Path location, ResourceSet rs) throws IOException {
registerEcoreMetamodelLocally(location, rs, emfLoadOptions);
}
/**
* Register all the packages found in the given Ecore metamodel locally.
*
* @param location the metamodel location, must be a valid file system path
* @param rs the Resource Set
* @param options the options
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void registerEcoreMetamodelLocally(
Path location,
ResourceSet rs,
Map<?,?> options) throws IOException {
if (!matcher.matches(location)) {
System.out.println("Attempting to load a metamodel without an *.ecore name, make sure the appropiate facotry has been registered.");
}
if (location.toString().contains("!")) {
throw new IllegalStateException("The provided path is jar resource, you need to copy the"
+ " contents to a file or use the InputStream alternative method.");
}
Resource r = rs.createResource(URI.createFileURI(location.toString()));
r.load(options);
for (EObject eo : r.getContents()) {
if (eo instanceof EPackage) {
registerEPackage((EPackage) eo, rs.getPackageRegistry());
}
}
}
/**
* Register all the packages found in the given Ecore metamodel locally.
*
* @param location the metamodel location, must be a valid file system path
* @param rs the Resource Set
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void registerEcoreMetamodelGlobally(Path location) throws IOException {
registerEcoreMetamodelGlobally(location, emfLoadOptions);
}
/**
* Register all the packages found in the given Ecore metamodel globally
*
* @param location the metamodel location, must be a valid file system path
* @param rs the Resource Set
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void registerEcoreMetamodelGlobally(Path location, Map<?,?> options) throws IOException {
if (!matcher.matches(location)) {
System.out.println("Attempting to load a metamodel without an *.ecore name, make sure the appropiate facotry has been registered.");
}
if (location.toString().contains("!")) {
throw new IllegalStateException("The provided path is jar resource, you need to copy the"
+ " contents to a file or use the InputStream alternative method.");
}
ResourceSet rs = new ResourceSetImpl();
Resource r = rs.createResource(URI.createFileURI(location.toString()));
r.load(options);
org.eclipse.emf.ecore.EPackage.Registry registry = EPackage.Registry.INSTANCE;
for (EObject eo : r.getContents()) {
if (eo instanceof EPackage) {
registerEPackage((EPackage) eo, registry);
}
}
}
/**
* Register all the packages found in the given Ecore metamodel locally. The metamodel is read
* from an input stream. This method is useful when loading metamodel from Class resources.
*
* @param name the name of the metamodel
* @param stream the input stream from with the metamodel can be loaded
* @param rs the Resource Set
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void registerEcoreMetamodelLocally(
String name,
InputStream stream,
ResourceSet rs) throws IOException {
registerEcoreMetamodelLocally(name, stream, rs, emfLoadOptions);
}
/**
* Register all the packages found in the given Ecore metamodel locally. The metamodel is read
* from an input stream. This method is useful when loading metamodel from Class resources.
*
* @param name the name of the metamodel
* @param stream the input stream from with the metamodel can be loaded
* @param rs the Resource Set
* @param options the options
* @throws IOException Signals that an I/O exception has occurred.
*/
public static void registerEcoreMetamodelLocally(
String name,
final InputStream stream,
final ResourceSet rs,
final Map<?,?> options) throws IOException {
boolean append = false;
try {
String ext = name.substring(name.lastIndexOf("."));
if (ext.equals(".ecore")) {
append = true;
}
}
catch (IndexOutOfBoundsException ex) {
append = true;
}
if (append) {
name = name + ".ecore";
}
Resource r = rs.createResource(URI.createFileURI(name));
r.load(options);
for (EObject eo : r.getContents()) {
if (eo instanceof EPackage) {
registerEPackage((EPackage) eo, rs.getPackageRegistry());
}
}
}
/**
* Register the EPackage and its nested packages in the given EPackage.Registry
* @param ep The EPackage
* @param registry The Registry
*/
public static void registerEPackage(EPackage ep, org.eclipse.emf.ecore.EPackage.Registry registry) {
registry.put(ep.getNsURI(), ep);
for (EPackage nep : ep.getESubpackages()) {
registerEPackage(nep, registry);
}
}
/**
* Register the EPackage and its nested packages in the given EPackage.Registry
* @param ep The EPackage
* @param registry The Registry
*/
public static void registerEPackageGlobally(EPackage ep) {
org.eclipse.emf.ecore.EPackage.Registry.INSTANCE.put(ep.getNsURI(), ep);
for (EPackage nep : ep.getESubpackages()) {
registerEPackageGlobally(nep);
}
}
}