Skip to content
Snippets Groups Projects
Commit 1a3c67c4 authored by Simon Barner's avatar Simon Barner
Browse files

Add EcoreSerializerBase, a base class to implement serializers to load and...

Add EcoreSerializerBase, a base class to implement serializers to load and save resources whose root element is of type {@code R}.
parent 22e91cac
No related branches found
No related tags found
No related merge requests found
/*--------------------------------------------------------------------------+
$Id$
| |
| Copyright 2016 ForTISS GmbH |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.kernel.utils;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
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.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl;
import org.osgi.framework.Bundle;
/**
* Base class to implement serializers to load and save resources whose root element is of type
* {@code R}.
*
* @author barner
* @author $Author$
* @version $Rev$
* @ConQAT.Rating YELLOW Hash: 55E1AD7060144688DF8479369724773A
*/
public abstract class EcoreSerializerBase<R extends EObject> {
/** Namespace URI used to serialize resource. */
private String eNsURI;
/** {@link EPackage} that contains {@link EClass}es contained in the resource. */
private EPackage ePackage;
/** Factory used to build instances of elements contained in the resource. */
private Resource.Factory resourceFactory;
/** Encoding of resource. */
private Charset charset;
/** Name of schema file. */
private String schemaFileName;
/**
* Constructs a new {@link EcoreSerializerBase}.
*
* @param eNsURI
* Initializer for {@link #eNsURI}.
* @param ePackage
* Initializer for {@link #ePackage}.
* @param resourceFactory
* Initializer for {@link #resourceFactory}.
* @param charset
* Initializer for {@link #charset}.
* @param schemaFileName
* Initializer for {@link #schemaFileName}. May be {@code null}.
*/
public EcoreSerializerBase(final String eNsURI, final EPackage ePackage,
final Resource.Factory resourceFactory, final Charset charset,
final String schemaFileName) {
this.eNsURI = eNsURI;
this.ePackage = ePackage;
this.resourceFactory = resourceFactory;
this.charset = charset;
this.schemaFileName = schemaFileName;
}
/**
* Loads a resource from a file and returns its root element.
*
* @param pathName
* Path to file to be loaded
* @return Root element of resource.
*
* @throws IOException
*/
public final R load(final String pathName) throws IOException {
return load(createLoadURI(pathName));
}
/**
* Loads a resource from a file and returns its root element.
*
* @param uri
* Path to file to be loaded
* @return Root element of resource.
*
* @throws IOException
*/
public final R load(final URI uri) throws IOException {
ResourceSet resourceSet = createResourceSet(resourceFactory);
Resource resource = resourceSet.getResource(uri, true);
return getRootElement(resource.getContents().get(0));
}
/**
* Saves a EMF model to a file.
*
* @param rootElement
* Root element of model to serialized to XML.
* @param pathName
* File to which configuration is to be written to.
*
* @throws IOException
*/
public final void save(final R rootElement, final String pathName) throws IOException {
save(rootElement, createSaveURI(pathName));
}
/**
* Saves a EMF model to a file.
*
* @param rootElement
* Root element of model to serialized to XML.
* @param uri
* {@link URI} to which configuration is to be written to.
*
* @throws IOException
*/
public final void save(final R rootElement, final URI uri) throws IOException {
ResourceSet resourceSet = createResourceSet(new XMLResourceFactoryImpl());
Resource resource = resourceSet.createResource(uri);
if(resource instanceof XMLResource) {
((XMLResource)resource).setEncoding(charset.name());
}
resource.getContents().add(rootElement);
resource.save(getOptions());
}
/**
* Returns the effective options to be used for serialization, i.e. the options returned by
* {@link #getSpecificOptions()} modified to apply some enforced options.
*/
private Map<Object, Object> getOptions() {
Map<Object, Object> options = getSpecificOptions();
// Enforce the use of extended meta-data annotations. This ensures to preserve the
// element/attribute capitalization, the serialization type of string only elements, etc. to
// be confirming to the original XSD.
options.put(XMLResource.OPTION_EXTENDED_META_DATA, Boolean.TRUE);
// If a schema file as been specifed, enforce creation of xsi:schemaLocation
if(schemaFileName != null) {
options.put(XMLResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);
}
return options;
}
/**
* Returns the options used in {@link #save(EObject, URI)}. Sub-classes may this method in
* order to configure the right set of options for the corresponding file format.
*/
protected Map<Object, Object> getSpecificOptions() {
Map<Object, Object> options = new HashMap<Object, Object>();
// Prefer lean files and omit default content
options.put(XMLResource.OPTION_KEEP_DEFAULT_CONTENT, Boolean.FALSE);
// Pre-requisite for mixed content (e.g., also for comments)
options.put(XMLResource.OPTION_USE_LEXICAL_HANDLER, Boolean.TRUE);
return options;
}
/**
* Extracts the root element from the resources document root element. Must be implemented by
* sub-classes since this is specific to the corresponding file format.
*/
protected abstract R getRootElement(EObject contents);
/** Converts the given {@code pathName} into a file {@link URI}. */
protected final URI createFileURI(final String pathName) {
return URI.createFileURI(pathName);
}
/**
* Converts the given {@code bundlePathName} into a {@link URI} within the given {@link Bundle}.
*
* @throws IOException
*/
protected final URI createBundleURI(final String bundlePathName, final Bundle bundle)
throws IOException {
URL url = FileLocator.toFileURL(FileLocator.find(bundle, new Path(bundlePathName), null));
String pathName = url.getFile();
return URI.createFileURI(pathName);
}
/**
* From the given {@code pathName}, derives the URI that is actually being {@link #load(String)}
* ed. Sub-classes may override this method, e.g. to load files from a different context (such
* as a {@link Bundle}).
*
* @throws IOException
*/
protected URI createLoadURI(final String pathName) throws IOException {
return createFileURI(pathName);
}
/**
* From the given {@code pathName}, derives the URI to which the model is actually being
* {@link #save(EObject, String)}ed. Sub-classes may override this method, e.g. to save files
* from a different context (such as a {@link Bundle}).
*
* @throws IOException
*/
protected URI createSaveURI(final String pathName) throws IOException {
return createFileURI(pathName);
}
/**
* Creates a {@link ResourceSet} and configures it with the given
* {@link org.eclipse.emf.ecore.resource.Resource.Factory}.
*
* @throws IOException
*/
private final ResourceSet createResourceSet(final Resource.Factory resourceFactory)
throws IOException {
ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.getPackageRegistry().put(eNsURI, ePackage);
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap()
.put(Resource.Factory.Registry.DEFAULT_EXTENSION, resourceFactory);
// If specified, add schema file to xsi:schemaLocation (enforces OPTION_SCHEMA_LOCATION).
if(schemaFileName != null) {
Resource packageResource = resourceSet.createResource(URI.createURI(schemaFileName));
packageResource.getContents().add(ePackage);
}
return resourceSet;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment