Jump to: navigation, search

Difference between revisions of "Henshin Interpreter"

(Loading)
Line 1: Line 1:
The Henshin interpreter is the default engine for executing model transformations defined in Henshin. The interpreter can be invoked either using a wizard or programmatically.
+
The Henshin interpreter is the default engine for executing model transformations defined in Henshin. The interpreter can be invoked either using a wizard or programmatically using an API.
  
 
__TOC__
 
__TOC__
Line 19: Line 19:
 
== Interpreter API ==
 
== Interpreter API ==
  
The interpreter can be also invoked programatically, either as an IApplication in Eclipse or as a simple stand-alone Java app.
+
The interpreter can be also invoked programatically, either as an IApplication in Eclipse or as a simple stand-alone Java application.
  
Make sure you have all dependencies fulfilled to the Henshin runtime and to EMF. Then you can invoke the interpreter as shown below. Particularly, you should include the model and the interpreter plug-in of Henshin. For examples, see also the Java source codes in the documented  [http://www.eclipse.org/modeling/emft/henshin/examples.php examples page].
+
Make sure you have all dependencies fulfilled to the Henshin runtime and to EMF. For Henshin, you should include the the '''model''' and the '''interpreter''' plug-in into your classpath (e.g. as a plug-in dependency). For examples, see also the Java source codes in the documented  [http://www.eclipse.org/modeling/emft/henshin/examples.php examples page].
  
=== Loading ===
+
=== Loading & Saving ===
  
For loading you can use the class '''HenshinResourceSet''', which provides some convenience methods. Below you can see how to load models and transformations.
+
For loading and saving of models and transformations you can use the class '''HenshinResourceSet''', which provides some convenience methods. Below you can see how to load models and transformations.
 
+
=== Transforming ===
+
  
 
<source lang="java">
 
<source lang="java">
import java.util.List;
+
// Create a resource set for the working directory "my/working/directory"
 +
HenshinResourceSet resourceSet = new HenshinResourceSet("my/working/directory");
  
import org.eclipse.emf.ecore.EObject;
+
// Load a model:
import org.eclipse.emf.henshin.interpreter.EmfEngine;
+
EObject root = resourceSet.getObject("mymodel.xmi");
import org.eclipse.emf.henshin.interpreter.RuleApplication;
+
import org.eclipse.emf.henshin.interpreter.util.Match;
+
import org.eclipse.emf.henshin.matching.EmfGraph;
+
import org.eclipse.emf.henshin.model.Rule;
+
import org.eclipse.emf.henshin.model.TransformationSystem;
+
import org.eclipse.emf.henshin.model.resource.HenshinResourceSet;
+
  
/**
+
// Load a transformation system:
* A benchmark constructing multiple levels of a Sierpinski triangle.
+
TransformationSystem system = resourceSet.getTransformationSystem("mytransformation.henshin");
*
+
* @see <a href="http://en.wikipedia.org/wiki/Sierpinski_triangle">Sierpinski Triangle</a>
+
*/
+
public class SierpinskiBenchmark {
+
  
  public static void main(String[] args) {
+
// Apply the transformation (see below)...
  
    // Create a resource set with a base directory:
+
// Save the result:
    HenshinResourceSet resourceSet =
+
resourceSet.saveObject(root, "result.xmi");
            new HenshinResourceSet("src/org/eclipse/emf/henshin/examples/sierpinski/model");
+
</source>
+
Note that all relative file paths will be resolved using the working directory of the resource set. You should make sure that you use a single resource set for all loading and saving operations. Dynamic EMF is supported by the resource set implementation and saveObject() will automatically add scheme-locations to the saved files.
    // Load the transformation system:
+
    TransformationSystem trasys = resourceSet.getTransformationSystem("sierpinski.henshin");
+
  
    // Load the first level of the Sierpinski triangle:
+
=== Transforming ===
    EObject container = resourceSet.getFirstRoot("sierpinski-start.xmi");
+
  
    // Initialize the Henshin interpreter:
+
Here is a typical use case for the interpreter:
    EmfGraph graph = new EmfGraph(container);
+
    graph.removeEObject(container);
+
    EmfEngine engine = new EmfEngine(graph);
+
  
    // Load the rule:
+
<source lang="java">
    Rule addTriangleRule = trasys.findRuleByName("AddTriangle");
+
// Prepare the engine:
 +
Engine engine = new EngineImpl();
  
    System.out.println(Runtime.getRuntime().maxMemory() / (1024 * 1024) + "MB available memory\n");
+
// Initialize the graph:
+
EGraph graph = new EGraphImpl();
    // Iteratively compute the Sierpinski triangle:
+
graph.addTree(root);
    int i = 1;
+
    while (true) {
+
+
// Find all matches:
+
long startTime = System.nanoTime();
+
RuleApplication addTriangle = new RuleApplication(engine, addTriangleRule);
+
List<Match> matches = addTriangle.findAllMatches();
+
long matchingTime = (System.nanoTime() - startTime) / 1000000;
+
+
System.out.println("Level: " + i);
+
System.out.println("Rule applications:" + matches.size());
+
System.out.println("Matching: " + matchingTime + "ms");
+
 
+
// Apply rule with all matches:
+
startTime = System.nanoTime();
+
for (Match match : matches) {
+
    addTriangle = new RuleApplication(engine, addTriangleRule);
+
    addTriangle.setMatch(match);
+
    addTriangle.apply();
+
}
+
long runtime = (System.nanoTime() - startTime) / 1000000;
+
  
System.out.println("Application: " + runtime + "ms");
+
// Find the main transformation unit:
System.out.println("Total: " + (matchingTime + runtime) + "ms");
+
TransformationUnit unit = system.findUnitByName("myMainUnit");
System.out.println("Nodes: " + graph.geteObjects().size());
+
System.out.println();
+
i++;
+
 
 
}
+
// Apply the unit:
    }
+
UnitApplication application = new UnitApplicationImpl(engine);
}
+
application.setUnit(unit);
 +
application.setEGraph(graph);
 +
application.execute(null);
 
</source>
 
</source>
 
=== Saving ===
 
 
If something goes wrong, you can always use the Eclipse debugger to find out what's going on (see [http://www.vogella.de/articles/EclipseDebugging/article.html here] for a tutorial).
 

Revision as of 08:19, 19 June 2012

The Henshin interpreter is the default engine for executing model transformations defined in Henshin. The interpreter can be invoked either using a wizard or programmatically using an API.

Interpreter Wizard

Henshin Interpreter Wizard

The interpreter wizard can be invoked by a right-click on a *.henshin file in the Package Explorer and selecting Henshin→Apply with Henshin.

In the first page of the wizard, you need to enter the following information:

  • Choose a transformation rule or unit to be applied.
  • Specify a model file to be transformed using the rule or unit.
  • Enter possible parameters of the rule or unit. Make sure that the type of the parameters is correctly set. Ignore means that the parameter is not set and will be matched automatically by the interpreter.

If you click Preview you should either see the modifications to the model or get a message that the rule or unit could not be applied. If you think it should be applicable but still get a message that it is not, make sure the parameters are all correctly set including their types.

If you click Transform the model will be transformed and saved, if possible.

Interpreter API

The interpreter can be also invoked programatically, either as an IApplication in Eclipse or as a simple stand-alone Java application.

Make sure you have all dependencies fulfilled to the Henshin runtime and to EMF. For Henshin, you should include the the model and the interpreter plug-in into your classpath (e.g. as a plug-in dependency). For examples, see also the Java source codes in the documented examples page.

Loading & Saving

For loading and saving of models and transformations you can use the class HenshinResourceSet, which provides some convenience methods. Below you can see how to load models and transformations.

// Create a resource set for the working directory "my/working/directory"
HenshinResourceSet resourceSet = new HenshinResourceSet("my/working/directory");
 
// Load a model:
EObject root = resourceSet.getObject("mymodel.xmi");
 
// Load a transformation system:
TransformationSystem system = resourceSet.getTransformationSystem("mytransformation.henshin");
 
// Apply the transformation (see below)...
 
// Save the result:
resourceSet.saveObject(root, "result.xmi");

Note that all relative file paths will be resolved using the working directory of the resource set. You should make sure that you use a single resource set for all loading and saving operations. Dynamic EMF is supported by the resource set implementation and saveObject() will automatically add scheme-locations to the saved files.

Transforming

Here is a typical use case for the interpreter:

// Prepare the engine:
Engine engine = new EngineImpl();
 
// Initialize the graph:
EGraph graph = new EGraphImpl();
graph.addTree(root);
 
// Find the main transformation unit:
TransformationUnit unit = system.findUnitByName("myMainUnit");
 
// Apply the unit:
UnitApplication application = new UnitApplicationImpl(engine);
application.setUnit(unit);
application.setEGraph(graph);
application.execute(null);