/*******************************************************************************
* Copyright (c) 2010-2015 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
*
* Contributors:
* TU Berlin, University of Luxembourg, SES S.A.
*******************************************************************************/
package de.tub.tfs.henshin.editor.commands.transformation_unit;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.NotificationImpl;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.henshin.interpreter.Assignment;
import org.eclipse.emf.henshin.interpreter.Match;
import org.eclipse.emf.henshin.interpreter.RuleApplication;
import org.eclipse.emf.henshin.interpreter.UnitApplication;
import org.eclipse.emf.henshin.interpreter.impl.EngineImpl;
import org.eclipse.emf.henshin.interpreter.impl.MatchImpl;
import org.eclipse.emf.henshin.interpreter.impl.UnitApplicationImpl;
import org.eclipse.emf.henshin.interpreter.util.HenshinEGraph;
import org.eclipse.emf.henshin.model.Attribute;
import org.eclipse.emf.henshin.model.Edge;
import org.eclipse.emf.henshin.model.Graph;
import org.eclipse.emf.henshin.model.Node;
import org.eclipse.emf.henshin.model.Unit;
import org.eclipse.gef.commands.Command;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import de.tub.tfs.henshin.editor.commands.rule.CreateNodeLayoutCommand;
import de.tub.tfs.henshin.editor.util.HenshinLayoutUtil;
import de.tub.tfs.henshin.model.layout.NodeLayout;
/**
* The Class ExecuteTransformationUnitCommand.
*
* @author Johann, nam
*/
public class ExecuteTransformationUnitCommand extends Command {
/** The graph. */
private Graph graph;
/** The transformation unit. */
private Unit transformationUnit;
/** The assignments. */
private Map<String, Object> assignments;
/** The unit application. */
private UnitApplicationImpl unitApplication;
private HenshinEGraph henshinGraph;
/** The henshin graph. */
// private HenshinGraph henshinGraph;
/**
* Instantiates a new execute transformation unit command.
*
* @param graph
* the graph
* @param transformationUnit
* the transformation unit
* @param assignments
* the assignments
*/
public ExecuteTransformationUnitCommand(Graph graph,
Unit transformationUnit,
Map<String, Object> assignments) {
super();
this.graph = graph;
this.transformationUnit = transformationUnit;
this.assignments = assignments;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.commands.Command#canExecute()
*/
@Override
public boolean canExecute() {
return graph != null && transformationUnit != null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.commands.Command#execute()
*/
@Override
public void execute() {
final List<Node> alteNodes = new ArrayList<Node>(graph.getNodes());
henshinGraph = new HenshinEGraph(graph);
EngineImpl emfEngine = new EngineImpl();
//emfEngine.getOptions().setInjective(true);
unitApplication = new UnitApplicationImpl(emfEngine,henshinGraph,transformationUnit ,null);
if (assignments != null) {
for (String parameter : assignments.keySet()) {
unitApplication.setParameterValue(parameter,
assignments.get(parameter));
}
}
try {
graph.eSetDeliver(false);
for (Node node : graph.getNodes()) {
node.eSetDeliver(false);
for (Attribute attr : node.getAttributes()) {
attr.eSetDeliver(false);
}
}
for (Edge edge : graph.getEdges()) {
edge.eSetDeliver(false);
}
Job j = new Job("Execution of " + transformationUnit.getName()
+ " on Graph " + graph.getName()) {
@SuppressWarnings("deprecation")
@Override
protected void canceling() {
this.getThread().stop(new Exception("Execution canceled!"));
super.canceling();
}
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
monitor.beginTask(
"Execute unit " + transformationUnit.getName()
+ " on Graph " + graph.getName(), -1);
if (!unitApplication.execute(null)) {
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
MessageDialog
.openError(null, "Execute Error",
"Transformation unit couldn't be executed.");
}
});
// MessageDialog.openError(null,
// "Execute Error",
// "Transformation unit couldn't be executed.");
} else {
// ----
List<Node> newNodes = new ArrayList<Node>(
graph.getNodes());
newNodes.removeAll(alteNodes);
// ------
createNodeLayouts(newNodes, alteNodes);
}
} catch (Exception ex) {
monitor.beginTask(
"Canceling execution and undoing changes.", -1);
try {
unitApplication.undo(null);
} catch (Exception ex2) {
}
monitor.done();
return Status.CANCEL_STATUS;
}
monitor.done();
return Status.OK_STATUS;
}
};
PlatformUI.getWorkbench().getProgressService()
.showInDialog(Display.getDefault().getActiveShell(), j);
j.setPriority(Job.LONG);
j.schedule();
int priority = 0;
Thread t = j.getThread();
if (t != null) {
priority = t.getPriority();
t.setPriority(Thread.MIN_PRIORITY);
}
Display d = Display.getDefault();
while (j.getResult() == null) {
if (!d.readAndDispatch())
;
d.sleep();
}
graph.eSetDeliver(true);
for (Node node : graph.getNodes()) {
node.eSetDeliver(true);
for (Attribute attr : node.getAttributes()) {
attr.eSetDeliver(true);
}
}
for (Edge edge : graph.getEdges()) {
edge.eSetDeliver(true);
}
NotificationImpl n = new org.eclipse.emf.common.notify.impl.NotificationImpl(
Notification.ADD, false, false) {
@Override
public Object getNotifier() {
// TODO Auto-generated method stub
return graph;
}
};
graph.eNotify(n);
for (Edge edge : graph.getEdges()) {
edge.eNotify(n);
}
for (Node node : graph.getNodes()) {
node.eNotify(n);
for (Attribute attr : node.getAttributes()) {
attr.eNotify(n);
}
}
if (t != null)
t.setPriority(priority);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.gef.commands.Command#undo()
*/
@Override
public void undo() {
unitApplication.undo(null);
}
/**
* Creates the node layouts.
*
* @param newNodes
* the new nodes
* @param oldNodes
* the old nodes
*/
private void createNodeLayouts(List<Node> newNodes, List<Node> oldNodes) {
for (Node n : newNodes) {
EObject o = henshinGraph.getNode2ObjectMap().get(n);
Node rhsNode = null;
for (RuleApplication rApplication : unitApplication
.getAppliedRules()) {
//TODO: Replace with correct code for handling layouts
HashMap<Node,EObject> nodeMapping = null;
try {
Match match = rApplication.getResultMatch();
Field field = MatchImpl.class.getDeclaredField("values");
field.setAccessible(true);
nodeMapping = (HashMap<Node, EObject>) field.get(match);
} catch (Exception ex){
}
if (nodeMapping != null){
for (Entry<Node, EObject> entry : nodeMapping.entrySet()) {
if (entry.getValue() == o) {
rhsNode = entry.getKey();
}
}
}
}
int r = new Random(System.currentTimeMillis()).nextInt(100) + 1;
int x = r;
int y = r;
if (rhsNode != null) {
NodeLayout rhsNodeLayout = HenshinLayoutUtil.INSTANCE
.getLayout(rhsNode);
x += rhsNodeLayout.getX();
y += rhsNodeLayout.getY();
}
(new CreateNodeLayoutCommand(n, x, y)).execute();
}
}
/**
* Gets the unit application.
*
* @return the unitApplication
*/
/**
* @return
*/
public synchronized UnitApplication getUnitApplication() {
return unitApplication;
}
}