blob: 02f1b6bb2e4ce3e6ee1a5cb8d47e7ab7860e356c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2019 Mia-Software and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Gabriel Barbier (Mia-Software) - initial API and implementation
* Nicolas Bros (Mia-Software) - Bug 335003 - [Discoverer] : Existing Discoverers Refactoring based on new framework
* Nicolas Bros (Mia-Software) - Bug 340149 - [Discovery] duplicate AtlLaunchHelper
* Nicolas Bros (Mia-Software) - Bug 340160 - [Discovery] non-wanted serialization of intermediate Java model in "Java to KDM"
* Nicolas Bros (Mia-Software) - Bug 341378 - AtlLaunchHelper : transformed models disappear randomly
*******************************************************************************/
package org.eclipse.modisco.util.atl.core.internal;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import org.eclipse.m2m.atl.drivers.emf4atl.ASMEMFModel;
import org.eclipse.m2m.atl.drivers.emf4atl.EMFModelLoader;
import org.eclipse.m2m.atl.engine.vm.AtlLauncher;
import org.eclipse.m2m.atl.engine.vm.AtlModelHandler;
import org.eclipse.m2m.atl.engine.vm.nativelib.ASMModel;
/**
* @author gbarbier
*
*/
public class AtlLaunchHelper {
public static class ModelInfo {
private final String modelName;
private final URI modelURI;
private final Resource resource;
private final String metamodelName;
private final URI metamodelUri;
/**
* @param name
* informative name of the model (such as "kdmInput" or
* "umlOutput")
* @param modelURI
* the {@link URI} of the model (if <code>resource</code> is
* not <code>null</code>, then this must be the URI of this
* {@link Resource})
* @param resource
* an already read resource, or <code>null</code> to
* deserialize the resource from the <code>modelURI</code>
* @param metamodelName
* the informative name of the metamodel corresponding to
* this model ("uml", "kdm", etc.)
* @param metamodelUri
* the URI of the metamodel
*/
public ModelInfo(final String name, final URI modelURI,
final Resource resource, final String metamodelName,
final URI metamodelUri) {
this.modelName = name;
this.modelURI = modelURI;
this.resource = resource;
this.metamodelName = metamodelName;
this.metamodelUri = metamodelUri;
}
public String getModelName() {
return this.modelName;
}
public URI getModelURI() {
return this.modelURI;
}
public Resource getResource() {
return this.resource;
}
public String getMetamodelName() {
return this.metamodelName;
}
public URI getMetamodelUri() {
return this.metamodelUri;
}
}
private EMFModelLoader modelLoader;
private void createResources() {
this.modelLoader = (EMFModelLoader) AtlModelHandler.getDefault(
AtlModelHandler.AMH_EMF).createModelLoader();
}
/**
* @param models
* @param inputModels
* @param outputModels
*/
private void initMetamodels(final Map<String, ASMModel> models,
final List<AtlLaunchHelper.ModelInfo> inputModels,
final List<AtlLaunchHelper.ModelInfo> outputModels)
throws IOException {
for (ModelInfo modelInfo : inputModels) {
if (!models.containsKey(modelInfo.getMetamodelName())) {
ASMEMFModel metamodel = this.modelLoader.loadModel(
modelInfo.getMetamodelName(),
this.modelLoader.getMOF(), modelInfo.getMetamodelUri());
models.put(modelInfo.getMetamodelName(), metamodel);
}
}
for (ModelInfo modelInfo : outputModels) {
if (!models.containsKey(modelInfo.getMetamodelName())) {
ASMEMFModel metamodel = this.modelLoader.loadModel(
modelInfo.getMetamodelName(),
this.modelLoader.getMOF(), modelInfo.getMetamodelUri());
models.put(modelInfo.getMetamodelName(), metamodel);
}
}
}
private void initModels(final Map<String, ASMModel> models,
final List<AtlLaunchHelper.ModelInfo> inputModels,
final List<AtlLaunchHelper.ModelInfo> outputModels)
throws IOException {
for (ModelInfo modelInfo : inputModels) {
Resource resource = modelInfo.getResource();
final ASMModel inputModel;
if (resource != null) {
// serialize in memory (because ATL doesn't take a Resource
// directly)
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
resource.save(byteArrayOutputStream, null);
ByteArrayInputStream inputStream = new ByteArrayInputStream(
byteArrayOutputStream.toByteArray());
inputModel = this.modelLoader.loadModel(
modelInfo.getModelName(),
models.get(modelInfo.getMetamodelName()), inputStream);
} else {
inputModel = this.modelLoader.loadModel(
modelInfo.getModelName(),
models.get(modelInfo.getMetamodelName()),
modelInfo.getModelURI());
}
models.put(modelInfo.getModelName(), inputModel);
}
for (ModelInfo modelInfo : outputModels) {
ASMEMFModel outputModel = (ASMEMFModel) this.modelLoader.newModel(
modelInfo.getModelName(),
URI.decode(modelInfo.getModelURI().toString()),
models.get(modelInfo.getMetamodelName()));
models.put(modelInfo.getModelName(), outputModel);
}
}
public List<Resource> runTransformation(final URL transformation,
final List<AtlLaunchHelper.ModelInfo> inputModels,
final List<AtlLaunchHelper.ModelInfo> outputModels)
throws IOException {
return runTransformation(transformation, inputModels, outputModels,
new ArrayList<URL>());
}
public List<Resource> runTransformation(final URL transformation,
final List<AtlLaunchHelper.ModelInfo> inputModels,
final List<AtlLaunchHelper.ModelInfo> outputModels,
final List<URL> superimposedTransformations) throws IOException {
final List<Resource> result = new ArrayList<Resource>();
final Map<String, ASMModel> models = new HashMap<String, ASMModel>();
createResources();
initMetamodels(models, inputModels, outputModels);
// get/create models
initModels(models, inputModels, outputModels);
// launch
final Map<String, Object> options = new HashMap<String, Object>();
options.put("continueAfterError", "true"); //$NON-NLS-1$ //$NON-NLS-2$
options.put("printExecutionTime", "true"); //$NON-NLS-1$ //$NON-NLS-2$
AtlLauncher.getDefault().launch(transformation, Collections.EMPTY_MAP,
models, Collections.EMPTY_MAP, superimposedTransformations,
options);
// store output models in the result array
for (ModelInfo omi : outputModels) {
ASMModel outputModel = models.get(omi.getModelName());
if (outputModel instanceof ASMEMFModel) {
ASMEMFModel asmEmfModel = (ASMEMFModel) outputModel;
Resource resource = asmEmfModel.getExtent();
result.add(moveToNewXMIResource(resource));
} else {
throw new RuntimeException("Model type not handled: " //$NON-NLS-1$
+ outputModel.getClass().getName());
}
}
return result;
}
public Resource runTransformation(final URL transformation,
final ModelInfo inputModel, final ModelInfo outputModel)
throws IOException {
final List<AtlLaunchHelper.ModelInfo> inputModels = new ArrayList<AtlLaunchHelper.ModelInfo>();
inputModels.add(inputModel);
final List<AtlLaunchHelper.ModelInfo> outputModels = new ArrayList<AtlLaunchHelper.ModelInfo>();
outputModels.add(outputModel);
List<Resource> results = runTransformation(transformation, inputModels,
outputModels);
if (results.size() > 0) {
Resource resultResource = results.get(0);
// move the contents of the ATL resource to a XMIResourceImpl
Resource newXMIResource = moveToNewXMIResource(resultResource);
newXMIResource.setURI(outputModel.getModelURI());
return newXMIResource;
}
return null;
}
// see Bug 341378 - AtlLaunchHelper : transformed models disappear randomly
private static Resource moveToNewXMIResource(final Resource resource) {
XMIResourceImpl xmiResourceImpl = new XMIResourceImpl();
ListIterator<EObject> listIterator = resource.getContents().listIterator();
while (listIterator.hasNext()) {
EObject eObject = listIterator.next();
listIterator.remove();
xmiResourceImpl.getContents().add(eObject);
}
return xmiResourceImpl;
}
}