package org.eclipse.emf.texo.generator;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.codegen.ecore.genmodel.GenModelPackage;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EModelElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.impl.EPackageRegistryImpl;
import org.eclipse.emf.ecore.plugin.EcorePlugin;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.Resource.Diagnostic;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.BasicExtendedMetaData;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.ExtendedMetaData;
import org.eclipse.emf.ecore.util.FeatureMap;
import org.eclipse.emf.ecore.xcore.XcorePackage;
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.XMLResourceFactoryImpl;
import org.eclipse.emf.ecore.xml.namespace.XMLNamespacePackage;
import org.eclipse.emf.ecore.xml.type.XMLTypePackage;
import org.eclipse.emf.texo.annotations.annotationsmodel.AnnotatedEStructuralFeature;
import org.eclipse.emf.texo.annotations.annotationsmodel.AnnotationsmodelPackage;
import org.eclipse.emf.texo.model.ModelFeatureMapEntry;
import org.eclipse.emf.texo.utils.Check;
import org.eclipse.emf.texo.utils.ModelUtils;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.xsd.XSDDiagnostic;
import org.eclipse.xsd.XSDDiagnosticSeverity;
import org.eclipse.xsd.XSDPackage;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.ecore.XSDEcoreBuilder;
import org.eclipse.xsd.util.XSDResourceFactoryImpl;
import org.eclipse.xsd.util.XSDResourceImpl;
import org.eclipse.xtext.common.types.TypesPackage;
import org.eclipse.xtext.xbase.XbasePackage;
/**
* Model/Ecore related convenience methods to for example read ecore and xsd's.
*
* @author <a href="mtaal@elver.org">Martin Taal</a>
*/
public class GeneratorUtils {
private static int ASTLEVEL = -1;
/**
* Get the latest AST parser, on Kepler this is AST4, on Luna it is AST8.
*/
public static int getASTLevel() {
if (ASTLEVEL == -1) {
Field[] declaredFields = AST.class.getDeclaredFields();
for (Field field : declaredFields) {
if (field.getName().equals("JLS8")) { //$NON-NLS-1$
ASTLEVEL = 8;
}
}
if (ASTLEVEL == -1) {
ASTLEVEL = 4;
}
}
return ASTLEVEL;
}
/**
* Determine if a property should be optional or not, if it is part of a featuremap then it may not be optional.
*/
public static boolean isOptional(EStructuralFeature eFeature) {
if (eFeature.isMany()) {
return false;
}
if (isPartOfGroup(eFeature)) {
return false;
}
return !eFeature.isRequired();
}
/**
* True if {@link EStructuralFeature#isDerived()} is true and the containing {@link EClass} is not a DocumentRoot.
*/
public static boolean setPropertyAccess(AnnotatedEStructuralFeature aFeature) {
// if we are part of a total code generation then don't ever set
// property access, it is determined by the presence of a member
if (aFeature.getAnnotatedEClass().getAnnotatedEPackage().getAnnotatedModel().isGeneratingSources()) {
return false;
}
// neither set it in case the feature is part of a feature map, if the ORM would access through the getter/setter
// then the featuremap entry would always be forced to the same feature (the setter sets the feature)
final EStructuralFeature eFeature = aFeature.getEStructuralFeature();
if (isPartOfGroup(eFeature)) {
return false;
}
return !ExtendedMetaData.INSTANCE.isDocumentRoot(eFeature.getEContainingClass()) && eFeature.isDerived();
}
/**
* @param value
* @return true if the value is null or has length 0 after trimming, false otherwise.
*/
public static boolean isEmptyOrNull(String value) {
return value == null || value.trim().length() == 0;
}
/**
* @param value
* @return true if the value is not null and not empty, false otherwise.
*/
public static boolean isNotEmptyAndNotNull(String value) {
return value != null && value.trim().length() > 0;
}
/**
* @return true if the passed EStructuralFeature is part of a group
*/
public static boolean isPartOfGroup(EStructuralFeature eFeature) {
// if the containing eclass is mixed then all efeatures are part
// of a group
return null != ExtendedMetaData.INSTANCE.getGroup(eFeature)
|| !ModelUtils.isMixed(eFeature) && ModelUtils.hasMixedEFeature(eFeature.getEContainingClass());
}
/**
* Create an unmodifiable list for a feature map for a specific EStructuralFeature.
*
* @param featureMap
* the feature map to extract the values for a specific EStructuralFeature from
* @param eStructuralFeature
* the EStructuralFeature to get all the values for
* @see FeatureMap
* @see Collections#unmodifiableList(List)
* @return
*/
@SuppressWarnings("unchecked")
public static <T, E extends ModelFeatureMapEntry<?>> List<T> createUnModifiableList(final Collection<E> featureMap,
final EStructuralFeature eStructuralFeature) {
final List<Object> result = new ArrayList<Object>();
for (final ModelFeatureMapEntry<?> entry : featureMap) {
// direct == should work, instances should be the same!
if (entry.getEStructuralFeature() == eStructuralFeature) {
result.add(entry.getValue());
}
}
return (List<T>) Collections.unmodifiableList(result);
}
/**
* @param feature
* the EStructuralFeature to check if it is an element
* @return true if the passed feature is an element
*/
public static boolean isElement(EStructuralFeature feature) {
return isKind(feature, "element"); //$NON-NLS-1$
}
/**
* @param feature
* the EStructuralFeature to check if it is a group
* @return true if the passed feature is a group
*/
public static boolean isGroup(EStructuralFeature feature) {
return isKind(feature, "group"); //$NON-NLS-1$
}
/**
* @param feature
* the EStructuralFeature to check if it is an attribute
* @return true if the passed feature is an attribute
*/
public static boolean isAttribute(EStructuralFeature feature) {
return isKind(feature, "attribute"); //$NON-NLS-1$
}
/**
* @param eClass
* the EStructuralFeatures of this EClass are searched for a mixed EStructuralFeature
* @return the EStructuralFeature of the EClass which is mixed (see {@link #isMixed(EStructuralFeature)}).
* @see EClass#getEAllStructuralFeatures()
*/
public static EStructuralFeature getMixedEStructuralFeature(EClass eClass) {
for (EStructuralFeature eStructuralFeature : eClass.getEAllStructuralFeatures()) {
if (ModelUtils.isMixed(eStructuralFeature)) {
return eStructuralFeature;
}
}
return null;
}
private static boolean isKind(EStructuralFeature feature, String kindValue) {
EAnnotation eAnnotation = feature.getEAnnotation(ExtendedMetaData.ANNOTATION_URI);
if (eAnnotation == null) {
return false;
}
final String kind = eAnnotation.getDetails().get("kind"); //$NON-NLS-1$
return kind != null && kind.compareTo(kindValue) == 0;
}
/**
* Creates a new instance of the {@link EPackage.Registry}. This registry contains a copy of the content of the global
* package registry.
*
* @return a new instance of the EPackage registry, is initially filled with the content of the global EPackage
* Registry.
*/
public static EPackage.Registry createEPackageRegistry() {
final EPackage.Registry registry = new EPackageRegistryImpl();
registry.put(XcorePackage.eNS_URI, XcorePackage.eINSTANCE);
registry.put(EcorePackage.eNS_URI, EcorePackage.eINSTANCE);
registry.put(XbasePackage.eNS_URI, XbasePackage.eINSTANCE);
registry.put(TypesPackage.eNS_URI, TypesPackage.eINSTANCE);
registry.put(GenModelPackage.eNS_URI, GenModelPackage.eINSTANCE);
registry.put(XMLTypePackage.eNS_URI, XMLTypePackage.eINSTANCE);
registry.put(XMLNamespacePackage.eNS_URI, XMLNamespacePackage.eINSTANCE);
registry.put(XSDPackage.eNS_URI, XSDPackage.eINSTANCE);
registry.put(AnnotationsmodelPackage.eNS_URI, AnnotationsmodelPackage.eINSTANCE);
// also add the 2 annotations models, solve using an eannotation in the epackages
if (null != EPackage.Registry.INSTANCE.get("http://www.eclipse.org/emf/texo/modelgenerator/modelannotations")) { //$NON-NLS-1$
final EPackage modelGenEPackage = EPackage.Registry.INSTANCE
.getEPackage("http://www.eclipse.org/emf/texo/modelgenerator/modelannotations"); //$NON-NLS-1$
registry.put(modelGenEPackage.getNsURI(), modelGenEPackage);
}
if (null != EPackage.Registry.INSTANCE.get("http://www.eclipse.org/emf/texo/orm/ormannotations")) { //$NON-NLS-1$
final EPackage modelOrmEPackage = EPackage.Registry.INSTANCE
.getEPackage("http://www.eclipse.org/emf/texo/orm/ormannotations"); //$NON-NLS-1$
registry.put(modelOrmEPackage.getNsURI(), modelOrmEPackage);
}
if (null != EPackage.Registry.INSTANCE.get("http://www.eclipse.org/eclipselink/xsds/persistence/orm")) { //$NON-NLS-1$
final EPackage ormEPackage = EPackage.Registry.INSTANCE
.getEPackage("http://www.eclipse.org/eclipselink/xsds/persistence/orm"); //$NON-NLS-1$
registry.put(ormEPackage.getNsURI(), ormEPackage);
}
return registry;
}
/**
* Reads EPackages from an ecore or xsd files.
*
* @param uri
* the URI pointing to ecore or xsd file
* @param registry
* the epackage registry to use
* @return the EPackages
*/
public static List<EPackage> readEPackage(final java.net.URI uri, EPackage.Registry registry, boolean useWsUris) {
final List<java.net.URI> list = new ArrayList<java.net.URI>();
list.add(uri);
return readEPackages(list, registry, useWsUris);
}
/**
* Reads EPackages from a set of ecore or xsd files.
*
* @param uris
* the array of URI's pointing to ecore or xsd files
* @param resourceSet
* the resourceSet to use, if null then a new one is created
* @param registry
* the registry to use when reading epackages
* @return the EPackages
*/
public static List<EPackage> readEPackages(final List<java.net.URI> uris, EPackage.Registry registry,
boolean useWsUris) {
final ResourceSet resourceSet = createGenerationResourceSet(registry);
return readEPackages(uris, resourceSet, registry, useWsUris);
}
/**
* Reads EPackages from a set of ecore or xsd files.
*
* @param uris
* the array of URI's pointing to ecore or xsd files
* @param resourceSet
* the resourceSet to use, if null then a new one is created
* @param registry
* the registry to use when reading epackages
* @return the EPackages
*/
public static List<EPackage> readEPackages(final List<java.net.URI> uris, ResourceSet resourceSet,
EPackage.Registry registry, boolean useWsUris) {
final List<URI> emfUris = new ArrayList<URI>();
for (final java.net.URI uri : uris) {
final String uriStr = uri.toString();
if (useWsUris) {
emfUris.add(URI.createPlatformResourceURI(uriStr, true));
} else {
emfUris.add(URI.createURI(uriStr));
}
}
return readEPackagesUsingEMFURI(emfUris, resourceSet, registry);
}
/**
* Reads EPackages from a set of ecore or xsd files.
*
* @param uris
* the array of EMF URI's pointing to ecore or xsd files
* @param registry
* the registry to use when reading epackages
* @return the EPackages
*/
public static List<EPackage> readEPackagesUsingEMFURI(final List<URI> uris, EPackage.Registry registry) {
final ResourceSet rs = createGenerationResourceSet(registry);
return readEPackagesUsingEMFURI(uris, rs, registry);
}
/**
* Reads EPackages from a set of ecore or xsd files.
*
* @param uris
* the array of EMF URI's pointing to ecore or xsd files
* @param registry
* the registry to use when reading epackages
* @return the EPackages
*/
public static List<EPackage> readEPackagesUsingEMFURI(final List<URI> uris, ResourceSet resourceSet,
EPackage.Registry registry) {
final List<EPackage> ePackages = new ArrayList<EPackage>();
// note passing resourcesets package registry to the xsdecore builder
// this ensures that epackages which refer to eachother are handled
// correctly
final XSDEcoreBuilder ecoreBuilder = new XSDEcoreBuilder(
new BasicExtendedMetaData(resourceSet.getPackageRegistry()));
ecoreBuilder.setValidate(true);
for (final URI emfURI : uris) {
if (emfURI.toString().endsWith("xsd")) { //$NON-NLS-1$
for (final EObject eObject : ecoreBuilder.generate(emfURI)) {
checkDiagnostics(ecoreBuilder);
final EPackage ePackage = ModelUtils.registerEPackage((EPackage) eObject, registry);
if (!ePackages.contains(ePackage)) {
ePackages.add(ePackage);
}
}
} else {
final Resource res = resourceSet.createResource(emfURI);
try {
res.load(null);
// code copied from EMF's EcoreEditor
// TODO: this code is probably not needed anymore
if (!res.getContents().isEmpty()) {
EObject rootObject = res.getContents().get(0);
Resource metaDataResource = rootObject.eClass().eResource();
if (metaDataResource != null && metaDataResource.getResourceSet() != null) {
resourceSet.getResources().addAll(metaDataResource.getResourceSet().getResources());
}
}
// resolve all to force checking to work
checkErrors(res);
final Iterator<EObject> it = res.getAllContents();
while (it.hasNext()) {
final Object obj = it.next();
if (obj instanceof EPackage) {
// TODO: should subepackages also be placed directly
// in the result
final EPackage ePackage = ModelUtils.registerEPackage((EPackage) obj, registry);
if (!ePackages.contains(ePackage)) {
ePackages.add(ePackage);
}
}
}
} catch (final Exception e) {
throw new IllegalArgumentException("Exception while loading resource from " //$NON-NLS-1$
+ emfURI.toString(), e);
}
}
}
// resolve and check them all
EcoreUtil.resolveAll(resourceSet);
// check again for errors
for (Resource res : resourceSet.getResources()) {
try {
checkErrors(res);
} catch (final Exception e) {
throw new IllegalArgumentException("Exception while resolving proxies for resource " //$NON-NLS-1$
+ res.getURI().toString(), e);
}
}
return ePackages;
}
/**
* Create a resource set which can be used in code generation.
*
* @param registry
* @return a new {@link ResourceSet}
*/
public static ResourceSet createGenerationResourceSet(EPackage.Registry registry) {
final ResourceSet rs = new ResourceSetImpl();
rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put("ecore", //$NON-NLS-1$
new EcoreResourceFactoryImpl());
rs.setPackageRegistry(registry);
rs.getURIConverter().getURIMap().putAll(EcorePlugin.computePlatformURIMap(false));
return rs;
}
private static void checkErrors(Resource res) {
if (res.getErrors().isEmpty() && res.getWarnings().isEmpty()) {
return;
}
final StringBuilder sb = new StringBuilder();
for (Diagnostic diagnostic : res.getErrors()) {
if (sb.length() > 0) {
sb.append("\n"); //$NON-NLS-1$
}
sb.append(diagnostic.getLocation() + " (" + diagnostic.getLine() //$NON-NLS-1$
+ "):" + diagnostic.getMessage());//$NON-NLS-1$
}
for (Diagnostic diagnostic : res.getWarnings()) {
if (sb.length() > 0) {
sb.append("\n"); //$NON-NLS-1$
}
sb.append(diagnostic.getLocation() + " (" + diagnostic.getLine() //$NON-NLS-1$
+ "):" + diagnostic.getMessage());//$NON-NLS-1$
}
throw new IllegalStateException(sb.toString());
}
private static void checkDiagnostics(XSDEcoreBuilder ecoreBuilder) {
final StringBuilder sb = new StringBuilder();
final List<XSDDiagnostic> diagnostics = ecoreBuilder.getDiagnostics();
for (XSDDiagnostic xsdDiagnostic : diagnostics) {
if (xsdDiagnostic.getSeverity() == XSDDiagnosticSeverity.ERROR_LITERAL
|| xsdDiagnostic.getSeverity() == XSDDiagnosticSeverity.FATAL_LITERAL) {
if (sb.length() > 0) {
sb.append("\n"); //$NON-NLS-1$
}
sb.append(xsdDiagnostic.getLocation() + " (" + xsdDiagnostic.getLine() + ":" + xsdDiagnostic.getColumn() //$NON-NLS-1$//$NON-NLS-2$
+ "):" + xsdDiagnostic.getMessage());//$NON-NLS-1$
}
}
if (sb.length() > 0) {
throw new IllegalStateException(sb.toString());
}
}
/**
* Read the ecore file belonging from the ecoreFileName location and register it with the nsURI passed in the global
* package registry.
*
* @param modelPackage
* the modelPackage for which the EPackage is read
* @param registry
* the registry to use when reading epackages
*/
public static void readEPackagesFromFile(final String nsUri, final String ecoreFileName, EPackage.Registry registry) {
Check.isNotEmpty(ecoreFileName, "Ecore file of ModelPackage may not be empty."); //$NON-NLS-1$
if (ecoreFileName != null && ecoreFileName.length() > 0) {
try {
// note the resource uri is the same as by which it is saved in
// the GenEPackage.getECoreFileContent
final Resource res = new EcoreResourceFactoryImpl().createResource(URI.createURI(nsUri));
final InputStream is = GeneratorUtils.class.getResourceAsStream(ecoreFileName);
res.load(is, Collections.EMPTY_MAP);
is.close();
// NOTE beware: for reference the below does not work if local
// references need to
// resolved, probably because the resource is created with the
// wrong uri
// final InputStream is =
// ecoreModelPackage.getClass().getResourceAsStream(ecoreFileName);
// final ResourceSet rs = new ResourceSetImpl();
// rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put("ecore",
// new
// EcoreResourceFactoryImpl());
// final Resource res =
// rs.createResource(URI.createURI(ecoreFileName));
// res.load(is, Collections.EMPTY_MAP);
// is.close();
final Iterator<?> it = res.getAllContents();
while (it.hasNext()) {
final Object obj = it.next();
if (obj instanceof EPackage) {
final EPackage epack = (EPackage) obj;
ModelUtils.registerEPackage(epack, registry);
}
}
} catch (final IOException e) {
throw new IllegalStateException("Exception while loading models from ecorefile " //$NON-NLS-1$
+ ecoreFileName);
}
}
}
/**
* @return the flattened list of all sub epackages.
*/
public static List<EPackage> getAllSubEPackages(final List<EPackage> ePackages) {
final List<EPackage> result = new ArrayList<EPackage>();
for (final EPackage ePackage : ePackages) {
result.add(ePackage);
result.addAll(getAllSubEPackages(ePackage));
}
return result;
}
/** @return all sub epackages from a parent package */
public static List<EPackage> getAllSubEPackages(final EPackage ePackage) {
final List<EPackage> subEPackages = new ArrayList<EPackage>();
for (final EPackage subEPackage : ePackage.getESubpackages()) {
subEPackages.add(subEPackage);
subEPackages.addAll(getAllSubEPackages(subEPackage));
}
return subEPackages;
}
/** @return the value of an annotation with a certain key */
public static String getEAnnotationValue(final EModelElement eModelElement, final String source, final String key) {
final EAnnotation eAnnotation = eModelElement.getEAnnotation(source);
if (eAnnotation == null) {
return null;
}
return eAnnotation.getDetails().get(key);
}
/**
* Creates a readable String from an {@link EStructuralFeature}.
*
* @param eFeature
* the EStructuralFeature for which a readable String is created.
* @return a readable String
*/
public static String toString(final EStructuralFeature eFeature) {
Check.isNotNullArgument(eFeature, "eFeature");//$NON-NLS-1$
return eFeature.getClass().getSimpleName() + ": " + eFeature.getEContainingClass().getName() //$NON-NLS-1$
+ "." + eFeature.getName(); //$NON-NLS-1$
}
/**
* Return the EPackage instance using a classname and a class loader. TODO: the classloader needs to be made
* configurable
*
* @param className
* the classname of the EPackage class instance
* @return the EPackage instance
*/
public static EPackage getEPackageInstance(final String className) {
try {
final Class<?> clz = Thread.currentThread().getContextClassLoader().loadClass(className);
final EPackage ePackage = (EPackage) clz.getField("eINSTANCE").get(null);//$NON-NLS-1$
return ePackage;
} catch (final Exception e) {
throw new IllegalArgumentException("Exception when getting EPackage instance " + className, e); //$NON-NLS-1$
}
}
/**
* Loads the xml/xmi referenced by the uri. Uses the standard {@link EPackage.Registry#INSTANCE}.
*
* Different {@link XMLResource} options are set to read xml which is based by a XSD.
*
* @param uri
* the uri pointing to a xml or xmi file
* @return the contents in the files
*/
public static List<EObject> loadResource(final String uri, EPackage.Registry registry) {
final ResourceSet resourceSet = createDataResourceSet(registry);
final Resource resource = resourceSet.createResource(URI.createURI(uri));
final Map<Object, Object> options = new HashMap<Object, Object>();
try {
options.put(XMLResource.OPTION_EXTENDED_META_DATA, Boolean.TRUE);
options.put(XMLResource.OPTION_USE_ENCODED_ATTRIBUTE_STYLE, Boolean.TRUE);
options.put(XMLResource.OPTION_USE_LEXICAL_HANDLER, Boolean.TRUE);
options.put(XMLResource.OPTION_LAX_WILDCARD_PROCESSING, Boolean.TRUE);
options.put(XMLResource.OPTION_LAX_FEATURE_PROCESSING, Boolean.TRUE);
resource.load(options);
} catch (final IOException e) {
throw new IllegalStateException("Exception when loading uri " + uri, e); //$NON-NLS-1$
}
return resource.getContents();
}
/**
* Creates a resource set which uses the passed in {@link EPackage.Registry} .
* <p/>
* This method registers the {@link XMLResourceFactoryImpl} and the {@link XMIResourceFactoryImpl} for resp. xml and
* xmi extensions.
*
* @return a new ResourceSet
*/
public static ResourceSet createDataResourceSet(final EPackage.Registry registry) {
final ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.setPackageRegistry(registry);
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xml", //$NON-NLS-1$
new XMLResourceFactoryImpl());
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xmi", //$NON-NLS-1$
new XMIResourceFactoryImpl());
return resourceSet;
}
/**
* Read XML Schemas from a xsd file defined by the uri.
*
* @param uri
* the uri should point to a xsd file
* @return the list of XSD Schema objects (is often only one)
* @see URI#createURI(String)
* @see #getXSDResourceSet()
*/
public static List<XSDSchema> getXSDSchemas(final String uri, EPackage.Registry registry) {
final List<XSDSchema> xsdSchemas = new ArrayList<XSDSchema>();
final ResourceSet resourceSet = getXSDResourceSet(registry);
final Resource resource = resourceSet.getResource(URI.createURI(uri), true);
for (final EObject eObject : resource.getContents()) {
// TODO: can it ever be anything else?
if (eObject instanceof XSDSchema) {
xsdSchemas.add((XSDSchema) eObject);
}
}
return xsdSchemas;
}
/**
* Create a {@link ResourceSet} which can be used to read {@link XSDSchema} objects from a xsd file. This resource set
* has extension mappings for: wsdl, xsd and ecore.
*
* @return a resource set which can be used to read xsd's
* @see XSDResourceFactoryImpl
* @see EcoreResourceFactoryImpl
*/
public static ResourceSet getXSDResourceSet(final EPackage.Registry registry) {
final ResourceSet result = new ResourceSetImpl();
result.setPackageRegistry(registry);
result.getLoadOptions().put(XSDResourceImpl.XSD_TRACK_LOCATION, Boolean.TRUE);
final Map<String, Object> extensionToFactoryMap = result.getResourceFactoryRegistry().getExtensionToFactoryMap();
extensionToFactoryMap.put("wsdl", new XSDResourceFactoryImpl()); //$NON-NLS-1$
extensionToFactoryMap.put("xsd", new XSDResourceFactoryImpl()); //$NON-NLS-1$
extensionToFactoryMap.put("ecore", new EcoreResourceFactoryImpl()); //$NON-NLS-1$
return result;
}
/**
* Convert an EPackage and all its sub epackages to a byte array.
*
* @param ePackage
* the EPackage to convert
* @param packageRegistry
* the EPackage.Registry to use. Should normally be the one provided by the
* {@link ModelManager#getPackageRegistry()}.
* @return the EPackage as byte array
*/
public static byte[] getEPackageAsByteArray(final EPackage ePackage, final EPackage.Registry packageRegistry) {
try {
Resource resource = ePackage.eResource();
if (resource == null) {
resource = createEcoreResource(ePackage.getNsURI(), packageRegistry);
resource.getContents().add(ePackage);
}
final Map<String, Object> options = new HashMap<String, Object>();
options.put(Resource.OPTION_ZIP, true);
final ByteArrayOutputStream os = new ByteArrayOutputStream();
resource.save(os, options);
return os.toByteArray();
} catch (final Exception e) {
throw new IllegalStateException(e);
}
}
/**
* Creates an EPackage (and all its sub epackages) from a byte array. The method first checks if the EPackage is
* already present in the passed registry. If so then the instance from the registry is returned and no conversion
* from the byte[] array is done.
*
* Note: this method *does not* register the read EPackages in the passed EPackage.Registry!
*
* @param uri
* the uri of the EPackage ({@link EPackage#getNsURI()}).
* @param bytes
* the EPackage as byte array
* @param packageRegistry
* the EPackage.Registry to use. Should normally be the one provided by the
* {@link ModelManager#getPackageRegistry()}.
* @return a new EPackage or the one already registered in the packageRegistry.
*/
public static EPackage createEPackage(final String nsUri, final byte[] bytes,
final EPackage.Registry packageRegistry) {
if (packageRegistry.getEPackage(nsUri) != null) {
return packageRegistry.getEPackage(nsUri);
}
try {
final ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
final Resource resource = createEcoreResource(nsUri, packageRegistry);
final Map<String, Object> options = new HashMap<String, Object>();
options.put(Resource.OPTION_ZIP, true);
resource.load(bais, options);
final EList<EObject> contents = resource.getContents();
final EPackage ePackage = (EPackage) contents.get(0);
return ePackage;
} catch (final Exception e) {
throw new IllegalStateException(e);
}
}
// private void registerSubPackages(final List<EPackage> ePackages,
// final EPackage.Registry packageRegistry) {
// for (EPackage ePackage : ePackages) {
// if (packageRegistry.containsKey(ePackage.getNsURI())) {
// throw new IllegalStateException("EPackage "
// + ePackage.getNsURI() + " is already registered");
// }
// packageRegistry.put(ePackage.getNsURI(), ePackage);
// registerSubPackages(ePackage.getESubpackages(), packageRegistry);
// }
// }
private static Resource createEcoreResource(final String uri, final EPackage.Registry packageRegistry) {
final ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.setPackageRegistry(packageRegistry);
final Resource.Factory resourceFactory = new EcoreResourceFactoryImpl();
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", resourceFactory); //$NON-NLS-1$
resourceSet.getResourceFactoryRegistry().getProtocolToFactoryMap().put("*", resourceFactory); //$NON-NLS-1$
return resourceSet.createResource(URI.createURI(uri));
}
}