blob: fa0f404edbe49c86240a19bf83ce820a6b0324b7 [file] [log] [blame]
/**
* <copyright>
* Copyright (c) 2010-2014 Henshin developers. All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
* </copyright>
*/
package org.eclipse.emf.henshin.interpreter.ui.util;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.emf.common.util.URI;
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.XMIResource;
import org.eclipse.emf.henshin.interpreter.ApplicationMonitor;
import org.eclipse.emf.henshin.interpreter.Assignment;
import org.eclipse.emf.henshin.interpreter.Engine;
import org.eclipse.emf.henshin.interpreter.UnitApplication;
import org.eclipse.emf.henshin.interpreter.impl.AssignmentImpl;
import org.eclipse.emf.henshin.interpreter.impl.BasicApplicationMonitor;
import org.eclipse.emf.henshin.interpreter.impl.EngineImpl;
import org.eclipse.emf.henshin.interpreter.ui.HenshinInterpreterUIPlugin;
import org.eclipse.emf.henshin.interpreter.util.InterpreterUtil;
import org.eclipse.emf.henshin.model.Parameter;
import org.eclipse.emf.henshin.model.Unit;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
public class TransformOperation extends WorkspaceModifyOperation {
/**
* The unit to be applied.
*/
protected Unit unit;
/**
* Configuration parameters.
*/
protected Collection<ParameterConfig> paramCfgs;
/**
* Input Model URI.
*/
protected URI inputUri;
/**
* Output Model URI.
*/
protected URI outputUri;
public Unit getUnit() {
return unit;
}
public void setUnit(Unit unit, Collection<ParameterConfig> paramCfgs) {
this.unit = unit;
this.paramCfgs = paramCfgs;
}
public void setInputURI(URI inputUri) {
this.inputUri = inputUri;
}
public void setOutputURI(URI outputUri) {
this.outputUri = outputUri;
}
public URI getInputUri() {
return inputUri;
}
public URI getOutputUri() {
return outputUri;
}
public Object getParameterValue(String parameterName) {
ParameterConfig pCfg = getParameterConfiguration(parameterName);
if (pCfg == null) {
return null;
}
return pCfg.getValue();
}
public ParameterConfig getParameterConfiguration(String parameterName) {
for (ParameterConfig pCfg : paramCfgs) {
if (pCfg.getName().equals(parameterName)) {
return pCfg;
}
}
return null;
}
public Collection<ParameterConfig> getParameterConfigurations() {
return paramCfgs;
}
public Map<String, Object> prepareParameterValues() {
Map<String, Object> result = new HashMap<String, Object>();
for (ParameterConfig paramCfg : paramCfgs) {
if (paramCfg.isClear()) {
continue;
}
result.put(paramCfg.getName(), paramCfg.getValue());
}
return result;
}
@Override
protected void execute(final IProgressMonitor monitor)
throws CoreException, InvocationTargetException,
InterruptedException {
monitor.beginTask("", 10);
monitor.subTask("Initializing transformation...");
ResourceSet resourceSet;
if (unit.eResource() != null && unit.eResource().getResourceSet() != null) {
resourceSet = unit.eResource().getResourceSet();
} else {
resourceSet = new ResourceSetImpl();
}
Resource input = resourceSet.getResource(inputUri, true);
Assignment assignment = new AssignmentImpl(unit);
for (Entry<String, Object> entry : prepareParameterValues().entrySet()) {
Parameter param = unit.getParameter(entry.getKey());
if (param != null) {
assignment.setParameterValue(param, entry.getValue());
}
}
monitor.worked(2);
if (monitor.isCanceled()) {
return;
}
Engine engine = new EngineImpl();
ApplicationMonitor appMonitor = new BasicApplicationMonitor() {
private int apps = 0;
@Override
public boolean isCanceled() {
return canceled || monitor.isCanceled();
}
@Override
public void notifyExecute(UnitApplication app, boolean success) {
if (apps++ % 50 == 0) {
monitor.subTask("Applied " + app.getUnit()
+ (success ? "" : " (failed)")
+ ", " + app.getEGraph().size()
+ " objects");
}
}
};
try {
if (!InterpreterUtil.applyToResource(assignment, engine, input,
appMonitor) && !monitor.isCanceled()) {
throw new CoreException(
new Status(IStatus.WARNING,
HenshinInterpreterUIPlugin.PLUGIN_ID,
"Transformation could not be applied to given input model."));
}
} catch (Throwable t) {
// NOTE we should use an error dialog with a "details" section showing the caught exception
throw new CoreException(
new Status(IStatus.ERROR,
HenshinInterpreterUIPlugin.PLUGIN_ID,
"Error applying transformation: " + t.getMessage(), t));
}
monitor.worked(4);
if (monitor.isCanceled()) {
return;
}
monitor.subTask("Saving result...");
Resource output;
if (inputUri.equals(outputUri)) {
output = input;
} else {
output = resourceSet.createResource(outputUri);
output.getContents().addAll(input.getContents());
}
Map<Object, Object> options = new HashMap<Object, Object>();
options.put(XMIResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);
try {
output.save(options);
} catch (IOException e) {
throw new CoreException(new Status(IStatus.ERROR,
HenshinInterpreterUIPlugin.PLUGIN_ID,
"Error saving transformation result.", e));
}
monitor.worked(2);
if (monitor.isCanceled()) {
return;
}
if (outputUri.isPlatformResource()) {
IPath path = new Path(outputUri.toPlatformString(false));
IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
if (file != null) {
file.getParent().refreshLocal(2,
SubMonitor.convert(monitor, 2));
}
}
monitor.subTask("Finalizing transformation...");
monitor.done();
}
}