EGF Tutorial - Pattern. First steps. |
This first tutorial explains how to create and execute simple patterns with EGF. A pattern is a solution to a recurrent generation problem. A pattern is based on a language, for instance Jet for model-to-text transformations. The pattern technique allows pattern inheritance, delegation to other patterns in order to elaborate reusable and customizable generation solutions.
Pattern organization. Patterns are organized by pattern libraries. A pattern library contains a set of patterns and a set of pattern libraries.
Pattern nature. A pattern nature indicates which language the pattern implementation conforms to (e.g. Java, Jet).
Pattern views. A pattern is visualized with three different folders: 1) Overview, 2) Specification which represents the external view of a pattern, 3) Implementation which represents the internal view of a pattern and where the pattern is implemented.
The sequence of actions to create a pattern:
Create a pattern with the Jet nature.
Figure 1. Example of new pattern
Specification view. This view enables to set 1) the super-pattern of the current pattern when pattern inheritance is needed, 2) the pattern nature already set during the pattern creation, 3) the pattern parameters.
Pattern query and parameter. The pattern applies queries over a resource that the pattern consumes, for instance a model. Each query record is successively stored in a parameter. The record process is described in the pattern implementation.
Pattern query. EGF proposes a default model query. The query list is extensible.
Pattern parameter. The pattern type is either a class defined in an ecore model or a Java type (class or interface).
The sequence of actions to define pattern parameters and their query:
Create an EClass parameter with the Basic query to navigate over the model.
Figure 2. Pattern Specification View
Implementation view. This view enables to define pattern methods, the method orchestration, and local variables.
Pattern methods. Four methods are predefined: header, init, preCondition and footer. Header is used for instance to declare the Jet declaration, init for the initialization of local variables (cf. explanation below), preCondition to filter records onto a query result. The user creates as many as methods he wants to implement the pattern. Each pattern method contents conforms to the pattern nature, for instance Jet-based code.
Pattern method orchestration. The method orchestration defines the order to call available methods and patterns: methods local to the current pattern, methods from the super-patterns, pattern call with parameter context passing, pattern call with injection.
Pattern variables. The pattern variables are accessible by any method of the current pattern. The type is either a class defined in an ecore model or a Java type (class or interface). Pattern variables can be initialized in the init method, update and used in the pattern methods.
The sequence of actions to manage the implementation methods:
The sequence of actions to manage variables:
The sequence of actions to manage the method orchestration:
Implement the default body method. Add the following Jet code:
Hello <%= aClass.getName() %>!
The following figure depicts how patterns are onto a domain resource.
Figure 3. Pattern Execution
Pattern strategies. A pattern strategy indicates how to apply patterns onto a resource. For instance, a pattern-oriented strategy successively applies a set of patterns onto a resource; a model-oriented strategy applies a set of patterns successively onto each model element. The model-driven strategy takes care of the model element order while the pattern-oriented strategy does not.
Tasks to execute patterns. A task must put in action all the elements described before to process a pool of patterns. The task must know:
Domain resource. Patterns are applied onto a resource, such as a domain model.
Pattern execution engines. Patterns have a nature (e.g., Jet, Java). Then, at execution time, an engine executes a pattern according its nature. On the pattern flow, different pattern execution engines can be activated.
Reporter. A reporter is typically useful for model-to-text transformation. Each pattern provides an output result that must be consolited in a files or several files. A reporter serves to report the result of the pattern implementation, for instance on the console or in a file.
A task is used to put in action pattern execution. This task must know: 1) the pattern or pattern library list, 2) the domain model, 3) the pattern strategy, and 4) the reporter. This tutorial uses the Model-driven pattern strategy. The use of pattern reporter is explained below.
The sequence of actions to create a task for pattern execution:
Apply the pattern library created before. Example of domain: platform:/plugin/org.eclipse.egf.model/model/Fcore.ecore.
Figure 4. Pattern Task
Finally, execute the factory component.
Reporter class. A reporter is a Java class which implements the PatternExecutionReporter class.
Collecting the result. There are two methods to collect the result of one pattern execution: 1) the loopFinished method collects the result for one pattern and for one query tuple, 2) the executionFinished method collects the result for one pattern, which is the aggregation of the loopFinished method results.
Reporting the result. The result is generally reported in a file.
For more complex reports, refer to org.eclipse.egf.emf.docgen.html plug-in which examplifies the case of result in a file and a specific folder.
1. Create a reporter Java class like this one:
Package org.eclipse.egf.examples.uc1.reporter; import java.util.Map; import org.eclipse.egf.model.pattern.PatternContext; import org.eclipse.egf.model.pattern.PatternExecutionReporter; public class MyReporter implements PatternExecutionReporter{ @Override public void executionFinished(String output, PatternContext context) { // Message on the default console System.out.println("Result of pattern:\n"+output); // Message on the EGF console EGFCorePlugin.getDefault().logInfo("Result of pattern:\n"+output); } @Override public void loopFinished(String output, PatternContext context, Map < String, Object > parameterValues) { // TODO Auto-generated method stub } }
2. Complete the task with the reporter parameter:
The pattern contents is translated into an executable form. This takes into account pattern inheritance and other pattern mechanisms not explained in this tutorial (e.g., pattern call). Next, at execution time, a pattern engine, specific to the pattern nature, executes a pattern.
Patterns are translated on the fly. One case requires to manually force pattern rebuild: pattern inheritance. Indeed, children are not notified that a super-pattern in the hierarchy is update. To force this translation: