/* * grEMF * * Copyright (C) 2006-2012 Institute for Software Technology * University of Koblenz-Landau, Germany * ist@uni-koblenz.de * * For bug reports, documentation and further information, visit * * https://github.com/jgralab/gremf * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see <http://www.gnu.org/licenses>. * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining * it with Eclipse (or a modified version of that program or an Eclipse * plugin), containing parts covered by the terms of the Eclipse Public * License (EPL), the licensors of this Program grant you additional * permission to convey the resulting work. Corresponding Source for a * non-source form of such a combination shall include the source code for * the parts of JGraLab used as well as that of the covered work. */ package de.uni_koblenz.gremf.resource; import java.io.Closeable; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import javax.xml.stream.FactoryConfigurationError; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import org.eclipse.emf.common.CommonPlugin; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.impl.ResourceFactoryImpl; import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl; import de.uni_koblenz.gremf.GrEMFIO; import de.uni_koblenz.gremf.GrEMFType; import de.uni_koblenz.jgralab.GraphIOException; import de.uni_koblenz.jgralab.schema.Schema; /** * Factory for creating grEMF specific resources<br> * This factory needs to be registered: * * <pre> * {@code * <extension point="org.eclipse.emf.ecore.extension_parser"> * <parser type="*" class="de.uni_koblenz.gremf.resource.GrEMFResourceImpl"/> * </extension> * } * </pre> * * or stand-alone<br> * * <pre> * {@code * Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap() * .put( "*", new GrEMFResourceFactoryImpl()); * } * </pre> * * @see {@link de.uni_koblenz.gremf.resource.GrEMFSchemaResourceImpl * GrEMFResourceImpl} (grEMF resource implementation) * */ public class GrEMFResourceFactoryImpl extends ResourceFactoryImpl { private static String XML_NS_PREFIX = "xml"; private static String XML_NS_URI = "http://www.w3.org/XML/1998/namespace"; private static String XMI_NS_PREFIX = "xmi"; private static String XMI_NS_URI = "http://www.omg.org/XMI"; private static String XSI_NS_URI = "http://www.w3.org/2001/XMLSchema-instance"; private static String XSI_SCHEMA_LOCATION = "schemaLocation"; private enum ResourceType { GREMF_SCHEMA, GREMF_INSTANCE, TG, OTHER } private boolean acceptEcores = false; /** * Sets the value that specifies whether files ending with .ecore * should be loaded as grEMF schema. The default is false, in that * case .ecore files are loaded with the EcoreResourceFactory and * not with grEMF. * * @param val the new value */ public void setLoadDotEcoreFilesAsGremf(boolean val){ this.acceptEcores = val; } /** * known, i.e. already loaded, schemas mapped to their qualified name */ Map<String, Schema> knownSchemas; @Override public Resource createResource(URI uri) { URI localURI = CommonPlugin.asLocalURI(uri); switch (this.getResourceType(localURI)) { case GREMF_SCHEMA: return new GrEMFSchemaResourceImpl(localURI); case GREMF_INSTANCE: return new GrEMFInstanceResourceImpl(localURI); case TG: Schema schema = this.getSchema(localURI); // if (schema != null) { // saving in empty file has no schema but // graph knows it return new TgResourceImpl(localURI, schema); // } default: return new XMIResourceImpl(uri); } } private ResourceType getResourceType(URI uri) { if (uri.fileExtension() == null) { return ResourceType.OTHER; } if (uri.fileExtension().equals("gremf")) { return ResourceType.GREMF_SCHEMA; }else if(this.acceptEcores && uri.fileExtension().equals("ecore")){ return ResourceType.GREMF_SCHEMA; } else if (uri.fileExtension().equals("tg")) { return ResourceType.TG; } else { return this.investigateResourceFile(uri); } } /** * Determines the type of the resource: OTHER or GREMF_INSTANCE<br> * Therefore, the file is parsed until the type can be determined * * @param uri * @return */ private ResourceType investigateResourceFile(URI uri) { ResourceType type = ResourceType.OTHER; InputStream in = null; XMLStreamReader parser = null; try { in = new FileInputStream(uri.path()); parser = XMLInputFactory.newInstance().createXMLStreamReader(in); while (parser.hasNext()) { if (parser.next() == XMLStreamConstants.START_ELEMENT) { if (!XMI_NS_PREFIX.equals(parser.getPrefix()) && !XMI_NS_URI.equals(parser.getNamespaceURI()) && !XML_NS_PREFIX.equals(parser.getPrefix()) && !XML_NS_URI.equals(parser.getNamespaceURI()) && (EPackage.Registry.INSTANCE.getEPackage(parser .getNamespaceURI()) instanceof GrEMFType)) { // current namespace belongs to a grEMF package type = ResourceType.GREMF_INSTANCE; break; } if (parser.getAttributeValue(XSI_NS_URI, XSI_SCHEMA_LOCATION) != null) { String[] parts = parser.getAttributeValue(XSI_NS_URI, XSI_SCHEMA_LOCATION).split(" "); for (int i = 0; (i + 1) < parts.length; i += 2) { if (parts[i + 1].matches("(.*).gremf") || (EPackage.Registry.INSTANCE .getEPackage(parts[i]) instanceof GrEMFType)) { // schema location refers to grEMF schema type = ResourceType.GREMF_INSTANCE; break; } } break; } } } } catch (XMLStreamException e) { e.printStackTrace(); } catch (FactoryConfigurationError e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { close(parser); close(in); } return type; } private Schema getSchema(URI localURI) { try { if (this.knownSchemas == null) { this.knownSchemas = new HashMap<String, Schema>(); } Schema schema = GrEMFIO.loadSchemaFromFile(localURI.path()); // if already loaded, use the loaded schema for preserving the // object identities if (this.knownSchemas.containsKey(schema.getQualifiedName())) { schema = this.knownSchemas.get(schema.getQualifiedName()); } else { this.knownSchemas.put(schema.getQualifiedName(), schema); } return schema; } catch (GraphIOException e) { e.printStackTrace(); System.err.println("can not load " + localURI); return null; } } private static void close(Object closeable) { if (closeable == null) { return; } try { if (closeable instanceof Closeable) { ((Closeable) closeable).close(); } else if (closeable instanceof XMLStreamReader) { ((XMLStreamReader) closeable).close(); } } catch (IOException e) { } catch (XMLStreamException e) { } } }