Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "VIATRA/Integration/MWE2 Integration"

(Finished up modifications)
Line 4: Line 4:
 
== Motivation ==
 
== Motivation ==
  
Define heterogeneous model transformation chains using a specialized description language.
+
Defining heterogeneous model transformation chains using a specialized description language.
*Sequence of model transformation steps can be easily specified and maintained.
+
* Sequence of model transformation steps can be easily specified and maintained.
*Nontrivial side-effect relations between transformation steps can be handled.
+
* Nontrivial side-effect relations between transformation steps can be handled.
*The execution of event-driven transformation can be controlled.
+
* The execution of event-driven transformations can be explicitly controlled.
*Because of the specialized language, the description code base is short and easily expandable.
+
* Because of the specialized language, the description code base is short and easily expandable.
  
 
== MWE 2 Basics ==
 
== MWE 2 Basics ==
Line 16: Line 16:
 
== VIATRA MWE2 Integration Library ==
 
== VIATRA MWE2 Integration Library ==
  
The VIATRA MWE2 Integration library provides support for defining complex transformation chains using Xtext MWE 2 workflows. As it can be seen on the figure below, due to the fact that the transformation chain itself is an MWE component, it can be easily integrated into higher level modeling workflows.  
+
===Overview===
 +
The VIATRA MWE2 Integration library provides support for defining complex transformation chains using Xtext MWE 2 workflows. As it can be seen on the figure below, the transformation chain itself is an MWE2 component, meaning that it can be easily integrated into higher level modeling workflows.  
  
 
[[File:VIATRAMWE2.png]]
 
[[File:VIATRAMWE2.png]]
  
A Transformation chain consists of numerous transformation steps and channels. This is required as certain transformations (for example event-driven transformations) do not follow the batch execution semantics of the MWE language. This way fine-grained incremental model transformations can be wrapped into these batch transformation chains. Transformation steps represent the individual transformations. Similar to the transformations themselves, these transformation steps define dependability relations towards each other. Channels can be used to determine these aforementioned dependability relations, as well as provide a direct communication method between transformation steps. If a step listens to a channel, the addition of a certain event to the channel will enable the execution of the step. After the execution has finished, new events are pushed to the site's target channels. The creation and processing of these events is the responsibility of the corresponding IEventFactory and IEventProcessor classes. The communicating transformation steps contain IListeningChannel and ITargetChannel objects. These wrapper classes bind together the channels with the factory (in case of target channels) or processor object (in case of listening channels) specified by the user. Note, that the transformation chain itself has input and output channels as well. These can be used to indicate the first and last transformation steps in the chain.
+
The transformation chain consists of different typed transformation steps. These are the following:
 +
 
 +
* Composite transformation steps: The composite steps are responsible for creating the control flow of the model transformation chain. These steps (Sequence, Loop, Conditional, Parallel) can contain other transformation steps. Once a given composite transformation step is executed, it will call its sub-steps in a specific manner (For example in case of Sequences, execute the contained steps in their order of appearance).
 +
* Model Transformation Steps: These steps cannot contain any child steps, meaning that they are used for implementing actual model transformations. They have access to the workflow context, to and from which they can push and pull data. They can also communicate directly with each other using parametric messages.
 +
 
 +
====Messaging====
 +
 
 +
* The MWE2 integration library implements basic publish/subscribe based messaging. Transformation steps can publish messages to certain topics. If an other transformation step is subscribed  to that given topic, it will receive the message as the execution token reaches the target step. Once the target step processes the message, the topic is informed about the act, and the message is deleted from the topic.
 +
 
 +
* Topic management: A message broker is responsible for the management of the individual topics. It enables the transformation steps to subscribe to any existing or new topic. It is also responsible for handing the incoming messages to the appropriate topic. Transformation steps can also query the message broker for the now messages on their subscribed topics.
 +
 
 +
* Message creation and processing: Message creation is done by message factories. These user specified objects can create messages with certain parameters. Message processors on the other hand are used by the transformation steps to process certain typed incoming messages.
 +
 
 +
* SubscribeTo and PublishTo objects: These objects represent publications and subscriptions on the transformation step's side. They store which message factory or processor should be used with the specified topic.
 +
 
 +
====Control flow====
 +
As mentioned before, the execution sequence of transformation steps can be defined by a standard control statement hierarchy, similar to imperative languages. The following control statements are supported:
 +
 
 +
* Transformation Chain: Transformation chains area the root elements of the control hierarchy. They can contain other transformation steps (they cannot contain transformation chains), which will be executed in order of their addition to the chain.
 +
 
 +
* Sequence: Sequences are basic control elements. They contain other transformation steps, and execute them in the order of their addition.
 +
 
 +
* Conditional: Conditional statements decide which one of their child transformation steps will be executed (these can be sequences, loops etc.), based on the validity of a condition specified by the user.
 +
 +
* For loop: Simple 'for' loop, it will iterate through its child elements, N times, where N is directly specified by the user using a numeric literal, or calculated dynamically.
 +
 
 +
* Foreach loop: Loop that iterates through an IIterable element provided by the user.
 +
 
 +
* While loop: A simple 'while' loop that will iterate through its child elements as long as the condition provided by the user appears to be valid.
 +
 
 +
* Do..While loop: Similar to the 'while' loop, however instead of checking the condition '''before''' each cycle, this one checks it '''after''' it.
 +
 
 +
* Parallel: Control statement that enables the parallel execution of transformation steps. Steps contained by this element will be assigned to independent threads. Note, that trasnformation steps that take part in a two way communication with one another should not be added to parallel sections, as in case of parallel execution timing errors can occur(lost messages, double messages etc.).
  
 
===Prerequisites and Installation===
 
===Prerequisites and Installation===
  
 +
====Update site installation====
 +
 +
'''No update site yet, This section will be revised after addition'''
 +
 +
====Source Installation====
 
In order to use this library, the following Eclipse plug-ins are required:
 
In order to use this library, the following Eclipse plug-ins are required:
*Eclipse Modeling 4.4 Luna recommended
+
*'''Eclipse Modeling 4.5 Mars''' recommended
*EMF-IncQuery 1.0.0 --> http://download.eclipse.org/incquery/updates/integration
+
*'''EMF-IncQuery 1.1.0''' --> http://download.eclipse.org/incquery/updates/integration
*MWE2 Language SDK 2.7.1 --> http://download.eclipse.org/modeling/tmf/xtext/updates/composite/releases/
+
*'''Xtext SDK 2.8.3''' --> http://download.eclipse.org/modeling/tmf/xtext/updates/composite/releases/
  
 
After the prerequisites are met clone the following repository and import the contained projects. Note, that it contains the source of the VIATRA framework as well.
 
After the prerequisites are met clone the following repository and import the contained projects. Note, that it contains the source of the VIATRA framework as well.
 
https://github.com/lunkpeter/org.eclipse.viatra
 
https://github.com/lunkpeter/org.eclipse.viatra
  
===Library Classes===
+
===Library Classes and Interfaces===
  
The library defines a set of base classes which represent the main elements the previously described transformation workflow semantics. User defined behavior can be added to these elements via inheritance.
+
The library defines a set of interfaces and abstract base classes which represent the main elements the previously described transformation workflow semantics. User defined behavior can be added via the extension of these elements
 
====Interfaces====
 
====Interfaces====
*'''ITransformationChain''': Represents a basic transformation chain. It provides an interface for defining transformation steps, as well as owns references to its inwards and outwards facing channels.
+
*'''ICompositeStep''': Defines the interface of composite transformation steps that can contain other steps.
 
*'''ITransformationStep''': Interface that defines the main entry points of transformation steps. The user defined functionality can be implemented in the execute, initialize and dispose methods.  
 
*'''ITransformationStep''': Interface that defines the main entry points of transformation steps. The user defined functionality can be implemented in the execute, initialize and dispose methods.  
*'''IChannel''': Defines methods for registering and receiving events.
+
*'''ITopic''': Defines the interface of topics. It includes methods for publishing and querying messages, as well as managing subscriptions.
*'''IEvent''': Interface for events, defines methods for getting and setting the event parameter.
+
*'''IMessage''': Interface for messages, defines methods for getting and setting the message parameter.
*'''IEventFactory''': Provides an interface for creating certain typed events. As the events can contain parameters, event- and parameter types are specified as generic type parameters.
+
*'''IMessageFactory''': Provides an interface for creating certain typed messages. As messages contain parameters, message- and parameter types are specified as generic type parameters.
*'''IEventProcessor''': Provides an interface for creating certain typed events. As the events can contain parameters, event- and parameter types are specified as generic type parameters.
+
*'''IMessageProcessor''': Provides an interface for creating certain typed messages. As messages can contain parameters, message- and parameter types are specified as generic type parameters.
*'''IListeningChannel''': Provides an interface for channels, that are specifically designed as listening channels. It defines easy to use methods for event processing, that the owner transformation step can use.
+
*'''ISubscribeTo''': Defines methods that enable the simple usage of topics and message factories.
*'''ITargetChannel''':Provides an interface for channels, that are specifically designed as target channels. It defines easy to use methods for event creation, that the owner transformation step can use.
+
*'''IPublishTo''': Defines methods that enable the simple usage of topics and message processors.
 +
*'''IMessageBroker''': Defines methods for the management of Topics and subscriptions.
 +
 
 +
=====Providers=====
 +
*'''IProvider''': Basic provider interface that defined methods for adding the actual workflow context to a given provider.
 +
*'''IConditionProvider''': Extends the IProvider, enables the user to provide dynamically calculated conditions for loops and conditional statements.
 +
*'''IIterableProvider''': Extends the IProvider, enables the user to provide IIterable objects for 'foreach' loops.
 +
*'''IIterationNumber''': Extends the IProvider, enables the user to dynamically calculate the number of iterations a 'for' loop does.
  
 
====Classes====
 
====Classes====
*'''MWE2TransformationChain''': The MWE2 based implementation of the ITransformationChain interface it represents the entire transformation workflow as an MWE IWorkflowComponent.
+
*'''TransformationChain''': Implements the ICompositeStep and  the MWE2 IWorkFlowComponent interface. As it is a composite step, it can contain additional transformation steps. In its execute method, the registered transformation steps are initialized and executed.  
It also defines a start and an end channel which can be used to identify the first and last transformation steps in the workflow. In its execute method, the registered transformation steps are initialized and a control event instance is sent to the start channel. After the initialization, the transformation chain object waits for the transformation workflow to finish, and disposes every transformation step.
+
*'''TransformationStep''':Abstract class that implements the ITransformationStep interface, that acts as a base class for user defined transformation steps. It incorporates the following features:
 +
** Support for containing ISubscribeTo and IPublishTo objects
 +
** Initialize the context attribute in the initialize() method
 +
** Process all incoming messages
 +
** Support the addition of user defined initialization, execute functionality and message publication (doInitialize(), doExecute(), publishMessages())
  
*'''MWE2TransformationStep''':Abstract ITransformationStep implementation, that acts as a base class for user defined transformation steps. It incorporates the following features:
+
*'''MessageBroker''': The MessageBroker is a singleton class that manages topics and subscriptions. It enables transformation steps to subscribe to topics, send and query messages, as well as acknowledge message processing (In case the message is successfully processed, the message itself will be removed from the topic's appropriate queue).
**In its run() method, it periodically checks if one of its listening channels contains an event.
+
**If events are contained it calls the execute() method, which has to be overridden by the user.
+
**It also provides helper methods for processing events, and sending them.
+
If any of the specified listening channels contain an event, this transformation step will trigger, consuming the given event.
+
  
*'''MWE2SyncTranformationStep''': Abstract child class of the MWE2TransformationStep. The main difference is, that this step will be activated if ALL of its listening channels contain processable events. If the step is activated, it removes an event from every listening channel, and executes the user defined functionality.
+
*'''Topic''': Topics contain subscribing transformation steps and messages sent to these subscribers. Messages are contained in a multi map whose key objects are transformation steps, while the value objects are lists of messages.
  
*'''MWE2Channel''': MWE 2 based IChannel implementation. It stores its contained events in a BlockingQueue object.
+
*'''SubscribeTo''': SubscribeTo objects contain an IMessageProcessor implementation and specify the Topic to which the transformation step has subscribed. The event processor is used for processing the messages that are provided by the topic. This ISubscribeTo implementation also features the priority property, which help in defining an order in which conflicting channels can be processed.
  
*'''MWE2ControlEvent''': MWE2 Control event implementation. It has no parameters, its only purpose is to enable the transformation step it is being sent to. This is the default event type, every newly created IListeningChannel and ITargetChannel object will use this event by default. Naturally, this can be overridden by the addition of custom factories and processors.
+
*'''PublishTo''': As specified in the IPublishTo interface, instances of this class contain an IMessageFactory object and the qualified name of a topic. The message factory is responsible for adding events to the aforementioned topic. The PublishTo class provides an easy to use interface for adding publishing messages.
  
*'''MWE2ControlEventFactory''': Event factory that is responsible for the instantiation of MWE2 Control events. This factory is the default factory of every newly instantiated ITargetChannel object.
+
=====Control Structures=====
 +
*'''Sequence''':Composite transformation step that implements a basic sequence control flow construction. It initializes and executes its contained steps in the same sequence they have been defined.
  
*'''MWE2ControlEventProcessor''': Event processor that processes MWE2 Control events. This processor is the default processor of every newly instantiated ITargetChannel object.
+
*'''Conditional''': Composite transformation step that implements an 'IF' style conditional construction. The condition is specified by an IConditionProvider which enables the specification of dynamically evaluated conditions. If the condition evaluation returns true, the ifTrue step is executed, if otherwise, the ifFalse step is executed. As the condition is evaluated in run time, both of the steps is initialized.
  
*'''MWE2ListeningChannel''': MWE2 based listening channel implementation. It contains an IChannel and an IEventProcessor implementation. The event processor is used for processing the events contained by the channel. This IListeningChannel implementation also features name and priority properties, which are used for directly referencing the channels and help in defining an order in which conflicting channels can be processed.
+
*'''ForLoop''': Composite transformation step that implements a 'for' style loop. The number of iterations can either be explicitly specified at compile time, using the iterations attribute, or dynamically calculated by an IIterationNumberProvider.  
  
*'''MWE2TargetChannel''': MWE 2 based ITargetChannel implementation. As specified in the ITargetChannel interface, instances of this class contain an IChannel and an IEventFactory object. The event factory is responsible for adding events to the channel. The TargetChannel class provides an easy to use interface for adding events to given channels, while also enabling the user to specify the soft type of the given channel, via adding a certain event factory.
+
*'''ForeachLoop''': Composite transformation step that implements a 'foreach' style loop. This kind of loop requires an IIterable object to iterate through. It is provided in run time by an IIterableProvider.
  
====Classes and interfaces used with event-driven transformations====
+
*'''WhileLoop''': Composite transformation step that implements a 'while' style loop. similar to the conditional step, the dynamically evaluated loop condition is provided by an IConditionProvider. The condition is evaluated before the current iteration.
  
*'''IController''': An interface that defines methods for explicitly controlling the execution of a fine-grained event-driven model transformation step.
+
*'''DoWhileLoop''': Composite transformation step that implements a 'do..while' style loop. similar to the while loop, the dynamically evaluated loop condition is provided by an IConditionProvider. In this case however, the condition is evaluated after the current iteration instead.
  
*'''IEnabler''': Interface that defines methods that can enable and disable a fine-grained, event-driven event driven transformation step.
+
*'''Parallel''': Composite transformation step that enables the parallel execution of transformation steps. Each transformation step will be assigned to a new thread.
 +
** Be advised: The parallel regions should be independent from each other, as there is no order of execution defined. This means, that typically parallel regions should not send each other parametric messages.  
  
*'''ISchedulerController''': Interface that defines functions which are used when an IController object also wraps an IncQuery EVM Scheduler.
+
=====Provider Implementations=====
 +
*'''BaseProvider''': Abstract base provider implementation that has an IWorkFlowContext attribute. This way inheriting classes can access the workflow context.
 +
*'''BaseIterationNumberProvider''': Basic iteration number provider that extend the BaseProvider abstract class and returns the number handed to it in its constructor.
  
*'''MWE2ControllableExecutor''': An IncQuery EVM Executor, that enables the MWE 2 workflow to control any IncQuery EVM based fine-grained event-driven transformation, provided that the transformation's ExecutionSchema is created with this executor. It also implements the IController interface which enables the workflow to explicitly start the execution of the transformation. The MWE2ControllableExecutor also provides information about the state of the transformation (i.e.: if the transformation has reached a steady state or not).
+
=====Example Messages, Factories and Processors=====
  
*'''MWE2EnablerExecutor''': An IncQuery EVM Executor, that enables the MWE 2 workflow to control any EVM based fine-grained event-driven transformation, provided that the transformation's ExecutionSchema is created with this executor. It also implements the IEnabler interface which means that based on the state of other transformation steps, the event-driven transformation can be enabled or disabled.
+
*'''StringMessage''': Basic message implementation that has a String typed parameter. It serves as a basic example for implementing custom messages.
  
*'''MWE2BaseControllableScheduler''': An EVM scheduler that enables the workflow to explicitly control the execution of a fine-grained event-driven transformation. As it implements the IController interface, its usage is similar to the MWE2ControllableExecutor. Internally, however, this solution uses a custom Scheduler object instead of an Executor. Using a custom Scheduler means, that the original IncQuery EVM Scheduler will be overridden.
+
*'''StringMessageFactory''': Message Factory that is responsible for the creation of StringMessage objects. Similar to the StringMessage class, this class serves as an example.
  
Detailed information about the usage of these classes can be found in the CPS example.
+
*'''StringMessageProcessor''': Message Processor that is responsible for processing StringMessage objects. It serves as an example for user defined message processors.
  
===Hello World Example===
+
 
The usage of these classes can be most effectively described via a simple 'Hello World' example:
+
==Examples==
 +
All of the below stated examples can be found in the mwe2integration.examples project in the following repository:
 +
*'''VIATRA examples repository'': http://git.eclipse.org/c/viatra/org.eclipse.viatra.examples.git/
 +
 
 +
===Basics===
 +
Typically the following steps are needed to create an MWE Transformation Chain:
  
 
*Create a new Eclipse plug-in project via File Menu --> New --> Project
 
*Create a new Eclipse plug-in project via File Menu --> New --> Project
 
*Create a new MWE2 file (in a not default package) using the similar method. If prompted, add the Xtext nature to the project.
 
*Create a new MWE2 file (in a not default package) using the similar method. If prompted, add the Xtext nature to the project.
 +
*Define custom transformation steps, messages and other classes supporting them.
 +
*Define workflow structure in the MWE2 file
 +
*Run the MWE2 workflow or integrate it in the transformation architecture.
 +
 +
===Simple Example===
 +
The usage of these classes can be most effectively described via a simple 'Hello World' example that defines two very simple transformation steps. These transformation steps do not communicate with each other using messages, and no complex control structures are used.
  
 
====Define Transformation Steps====
 
====Define Transformation Steps====
  
In the next step define the concrete transformation steps. Add these classes to the package created before.
+
In the following step define two very simple transformation steps. Add these classes to the package created before.
  
'''BatchTransformationStep.java'''
+
'''ExampleATransformationStep.java'''
  
 
<source lang="java">
 
<source lang="java">
import org.eclipse.emf.mwe2.runtime.workflow.IWorkflowContext;
+
/**
import org.eclipse.viatra.emf.mwe2integration.mwe2impl.MWE2TransformationStep;
+
* An example transformation step. User defined transformation steps should extend the abstract class
 +
* TransformationStep. It already implements the core features of transformation steps, namely the management of
 +
* publishings, subscriptions, as well as message processing and -creation.
 +
*
 +
*/
 +
class ExampleATransformationStep extends TransformationStep {
 +
override doInitialize(IWorkflowContext ctx) {
 +
//this method is called after the workflow context is assigned to the step
 +
//The transformation should be  initialized here
 +
System.out.println("Init A transformation")
 +
//The context can be used to access global variables
 +
//via ctx.get("String")
 +
}
 +
 +
override void doExecute() {
 +
//This method is executed during the execute method of a given transformation step,
 +
//after the received messages are processed and before outgoing messages are sent-
 +
//Run the transformation (or any other user defined function) here
 +
System.out.println("A transformation executed")
 +
}
 +
 +
override void dispose() {
 +
// Dispose functions
 +
System.out.println("Dispose A transformation")
 +
}
  
public class BatchTransformationStep extends MWE2TransformationStep {
+
//In this method the sending of messages can be defined
    @Override
+
//Typically the following implementation, which sends a given message type to all publishing topics,
    public void initialize(IWorkflowContext ctx) {
+
//is sufficient
        //The reference to the context is set
+
override void publishMessages() {
        this.context = ctx;
+
publishings.forEach[
        //Normally the transformation is initialized here.
+
publishMessage("MESSAGE A")
        System.out.println("Init batch transformation"); 
+
]
    }
+
}
   
+
    public void execute() {
+
        //Firstly the triggering event is processed
+
        processNextEvent();
+
        //The transformation is executed
+
        System.out.println("Batch transformation executed");
+
        //Events are sent to all target channels
+
        sendEventToAllTargets();
+
    }
+
   
+
    @Override
+
    public void dispose() {
+
        //Upon ending the runnable monitoring the incoming events needs to be stopped
+
        isRunning = false;
+
        //Dispose functions
+
        System.out.println("Dispose batch transformation");
+
    }
+
 
}
 
}
 
</source>
 
</source>
  
'''EventDrivenTransformationStep.java'''
+
'''ExampleBTransformationStep.java'''
  
 
<source lang="java">
 
<source lang="java">
import org.eclipse.emf.mwe2.runtime.workflow.IWorkflowContext;
+
/**
import org.eclipse.viatra.emf.mwe2integration.mwe2impl.MWE2TransformationStep;
+
* An example transformation step. User defined transformation steps should extend the abstract class
 +
* TransformationStep. It already implements the core features of transformation steps, namely the management of
 +
* publishings, subscriptions, as well as message processing and -creation.
 +
*
 +
* This class is the same as the A variant, it is needed as most of the examples call for two different
 +
* transformation steps
 +
*/
 +
class ExampleBTransformationStep extends TransformationStep {
 +
override doInitialize(IWorkflowContext ctx) {
 +
//this method is called after the workflow context is assigned to the step
 +
//The transformation should be  initialized here
 +
System.out.println("Init B transformation")
 +
//The context can be used to access global variables
 +
//via ctx.get("String")
 +
}
 +
 +
override void doExecute() {
 +
//This method is executed during the execute method of a given transformation step,
 +
//after the received messages are processed and before outgoing messages are sent-
 +
//Run the transformation (or any other user defined function) here
 +
System.out.println("B transformation executed")
 +
}
 +
 +
override void dispose() {
 +
// Dispose functions
 +
System.out.println("Dispose B transformation")
 +
}
  
public class EventDrivenTransformationStep extends MWE2TransformationStep {
+
//In this method the sending of messages can be defined
    @Override
+
//Typically the following implementation, which send a given message type to all publishing topics,
    public void initialize(IWorkflowContext ctx) {
+
//is sufficient
        System.out.println("Init event-driven transformation");
+
override void publishMessages() {
        this.context = ctx;
+
publishings.forEach[
    }
+
publishMessage("MESSAGE B")
 
+
]
    @Override
+
}
    public void execute() {
+
        processNextEvent();
+
        System.out.println("Send tick to event-driven transformation");
+
        sendEventToAllTargets();
+
    }
+
 
+
    @Override
+
    public void dispose() {
+
        isRunning = false;
+
        System.out.println("Dispose event-driven transformation");
+
 
+
    }
+
 
}
 
}
 
</source>
 
</source>
Line 160: Line 241:
 
====Define Transformation Structure====
 
====Define Transformation Structure====
  
Define the transformation chain structure using the MWE2 language. Make sure to include all the referenced packages (if the classes are in the same package as the MWE2 file, include that package as well), and that the module name matches the containing package.
+
Define the transformation chain structure using the MWE2 language. Make sure to include all the referenced packages (if the classes are in the same package as the MWE2 file, include that package as well), and that the module name should match the containing package as well.
  
'''TransformationDemo.mwe2'''
+
'''SimpleChainExample.mwe2'''
  
 
<source lang="java">
 
<source lang="java">
module org.eclipse.viatra.emf.mwe2orchestrator.transdemo
+
module org.eclipse.viatra.emf.mwe2integration.example.SimpleChainExample
  
 +
//Import the necessary libraries
 +
//Note, that the package containing the workflow needs to be imported as well (if it contains used resources)
 
import org.eclipse.viatra.emf.mwe2integration.*
 
import org.eclipse.viatra.emf.mwe2integration.*
 
import org.eclipse.viatra.emf.mwe2integration.mwe2impl.*
 
import org.eclipse.viatra.emf.mwe2integration.mwe2impl.*
import org.eclipse.viatra.emf.mwe2integration.demo.*
+
import org.eclipse.viatra.emf.mwe2integration.mwe2impl.messages.*
 
+
import org.eclipse.viatra.emf.mwe2integration.examples.resources.*
//The channels between the transformation steps are defined here
+
var chainStartChannel = MWE2Channel {}
+
var chainEndChannel = MWE2Channel {}
+
 
+
var BatchChannel = MWE2Channel {}
+
var EventDrivenChannel = MWE2Channel {}
+
  
 
//The workflow and components are defined in the usual MWE2 fashion
 
//The workflow and components are defined in the usual MWE2 fashion
 
Workflow {
 
Workflow {
//Add an MWE2TransformationChain component
+
//Add a TransformationChain component
component = MWE2TransformationChain {
+
//This component represents an MWE2 component that can contain numerous transformations
//define the start and end channels of the chain
+
component = TransformationChain {
startChannel = MWE2TargetChannel{channel = chainStartChannel}
+
//Add transformation steps
endChannel = MWE2ListeningChannel{channel = chainEndChannel}
+
//These classes all extend the TransformationStep abstract class, which implements their core features.
 
+
//User defined functionality can be added via overriding the doExecute() method
//define individual transformation steps
+
step = ExampleATransformationStep{}
transformationStep = EventDrivenTransformationStep {
+
//Multiple transformation steps will be executed in order of their definition
//register listening channels to which this step listens
+
//Note that in the other examples, more elaborate control constructions will be presented.
//Add the chainStartChannel as listening channel, this way the transformation
+
step = ExampleBTransformationStep{}
//chain can start the step sequence
+
listeningChannel = MWE2ListeningChannel{ channel = chainStartChannel}
+
listeningChannel = MWE2ListeningChannel{ channel = EventDrivenChannel}
+
//register target channels to which this step sends events
+
targetChannel = MWE2TargetChannel{channel = BatchChannel}
+
}
+
+
transformationStep = BatchTransformationStep {
+
listeningChannel = MWE2ListeningChannel{ channel = BatchChannel}
+
//Add the chainEndChannel as target channel, this way the transformation
+
//chain when to finish its execution.
+
targetChannel = MWE2TargetChannel{ channel = chainEndChannel}
+
}
+
 
}
 
}
 
//You can add additional regular MWE2 components here
 
//You can add additional regular MWE2 components here
Line 208: Line 272:
 
</source>
 
</source>
  
This example is included in the test project of the library.
+
After this, run the MWE2 file as an MWE 2 workflow.
 +
'''TODO finish'''
 +
 
 +
===Simple Example with Conditional===
 +
===Simple Example with Loops===
 +
===Complex Example with Messaging===
 +
===Complex Example with Parallel Execution===
  
 
===Complex Example (CPS)===
 
===Complex Example (CPS)===
Line 548: Line 618:
 
====Execution====
 
====Execution====
 
To run the specified workflow, simply run the mwe2 file as an 'MWE2 Workflow'.
 
To run the specified workflow, simply run the mwe2 file as an 'MWE2 Workflow'.
 +
 +
==Advanced Features==
 +
 +
===Wrapping fine grained event-driven transformations===
 +
 +
*'''IController''': An interface that defines methods for explicitly controlling the execution of a fine-grained event-driven model transformation step.
 +
 +
*'''IEnabler''': Interface that defines methods that can enable and disable a fine-grained, event-driven event driven transformation step.
 +
 +
*'''ISchedulerController''': Interface that defines functions which are used when an IController object also wraps an IncQuery EVM Scheduler.
 +
 +
*'''MWE2ControllableExecutor''': An IncQuery EVM Executor, that enables the MWE 2 workflow to control any IncQuery EVM based fine-grained event-driven transformation, provided that the transformation's ExecutionSchema is created with this executor. It also implements the IController interface which enables the workflow to explicitly start the execution of the transformation. The MWE2ControllableExecutor also provides information about the state of the transformation (i.e.: if the transformation has reached a steady state or not).
 +
 +
*'''MWE2EnablerExecutor''': An IncQuery EVM Executor, that enables the MWE 2 workflow to control any EVM based fine-grained event-driven transformation, provided that the transformation's ExecutionSchema is created with this executor. It also implements the IEnabler interface which means that based on the state of other transformation steps, the event-driven transformation can be enabled or disabled.
 +
 +
*'''MWE2BaseControllableScheduler''': An EVM scheduler that enables the workflow to explicitly control the execution of a fine-grained event-driven transformation. As it implements the IController interface, its usage is similar to the MWE2ControllableExecutor. Internally, however, this solution uses a custom Scheduler object instead of an Executor. Using a custom Scheduler means, that the original IncQuery EVM Scheduler will be overridden.
 +
 +
Detailed information about the usage of these classes can be found in the CPS example.
  
 
== Project Locations ==
 
== Project Locations ==

Revision as of 10:46, 17 July 2015

Transformation Chains Using VIATRA MWE 2 Integration

Motivation

Defining heterogeneous model transformation chains using a specialized description language.

  • Sequence of model transformation steps can be easily specified and maintained.
  • Nontrivial side-effect relations between transformation steps can be handled.
  • The execution of event-driven transformations can be explicitly controlled.
  • Because of the specialized language, the description code base is short and easily expandable.

MWE 2 Basics

Generic modeling workflows can be easily described via using the Xtext Modeling Workflow Engine. It enables the creation of components with various attributes, and it executes them in order. More, exact information about the Xtext MWE 2 can be found at https://www.eclipse.org/Xtext/documentation/306_mwe2.html

VIATRA MWE2 Integration Library

Overview

The VIATRA MWE2 Integration library provides support for defining complex transformation chains using Xtext MWE 2 workflows. As it can be seen on the figure below, the transformation chain itself is an MWE2 component, meaning that it can be easily integrated into higher level modeling workflows.

VIATRAMWE2.png

The transformation chain consists of different typed transformation steps. These are the following:

  • Composite transformation steps: The composite steps are responsible for creating the control flow of the model transformation chain. These steps (Sequence, Loop, Conditional, Parallel) can contain other transformation steps. Once a given composite transformation step is executed, it will call its sub-steps in a specific manner (For example in case of Sequences, execute the contained steps in their order of appearance).
  • Model Transformation Steps: These steps cannot contain any child steps, meaning that they are used for implementing actual model transformations. They have access to the workflow context, to and from which they can push and pull data. They can also communicate directly with each other using parametric messages.

Messaging

  • The MWE2 integration library implements basic publish/subscribe based messaging. Transformation steps can publish messages to certain topics. If an other transformation step is subscribed to that given topic, it will receive the message as the execution token reaches the target step. Once the target step processes the message, the topic is informed about the act, and the message is deleted from the topic.
  • Topic management: A message broker is responsible for the management of the individual topics. It enables the transformation steps to subscribe to any existing or new topic. It is also responsible for handing the incoming messages to the appropriate topic. Transformation steps can also query the message broker for the now messages on their subscribed topics.
  • Message creation and processing: Message creation is done by message factories. These user specified objects can create messages with certain parameters. Message processors on the other hand are used by the transformation steps to process certain typed incoming messages.
  • SubscribeTo and PublishTo objects: These objects represent publications and subscriptions on the transformation step's side. They store which message factory or processor should be used with the specified topic.

Control flow

As mentioned before, the execution sequence of transformation steps can be defined by a standard control statement hierarchy, similar to imperative languages. The following control statements are supported:

  • Transformation Chain: Transformation chains area the root elements of the control hierarchy. They can contain other transformation steps (they cannot contain transformation chains), which will be executed in order of their addition to the chain.
  • Sequence: Sequences are basic control elements. They contain other transformation steps, and execute them in the order of their addition.
  • Conditional: Conditional statements decide which one of their child transformation steps will be executed (these can be sequences, loops etc.), based on the validity of a condition specified by the user.
  • For loop: Simple 'for' loop, it will iterate through its child elements, N times, where N is directly specified by the user using a numeric literal, or calculated dynamically.
  • Foreach loop: Loop that iterates through an IIterable element provided by the user.
  • While loop: A simple 'while' loop that will iterate through its child elements as long as the condition provided by the user appears to be valid.
  • Do..While loop: Similar to the 'while' loop, however instead of checking the condition before each cycle, this one checks it after it.
  • Parallel: Control statement that enables the parallel execution of transformation steps. Steps contained by this element will be assigned to independent threads. Note, that trasnformation steps that take part in a two way communication with one another should not be added to parallel sections, as in case of parallel execution timing errors can occur(lost messages, double messages etc.).

Prerequisites and Installation

Update site installation

No update site yet, This section will be revised after addition

Source Installation

In order to use this library, the following Eclipse plug-ins are required:

After the prerequisites are met clone the following repository and import the contained projects. Note, that it contains the source of the VIATRA framework as well. https://github.com/lunkpeter/org.eclipse.viatra

Library Classes and Interfaces

The library defines a set of interfaces and abstract base classes which represent the main elements the previously described transformation workflow semantics. User defined behavior can be added via the extension of these elements

Interfaces

  • ICompositeStep: Defines the interface of composite transformation steps that can contain other steps.
  • ITransformationStep: Interface that defines the main entry points of transformation steps. The user defined functionality can be implemented in the execute, initialize and dispose methods.
  • ITopic: Defines the interface of topics. It includes methods for publishing and querying messages, as well as managing subscriptions.
  • IMessage: Interface for messages, defines methods for getting and setting the message parameter.
  • IMessageFactory: Provides an interface for creating certain typed messages. As messages contain parameters, message- and parameter types are specified as generic type parameters.
  • IMessageProcessor: Provides an interface for creating certain typed messages. As messages can contain parameters, message- and parameter types are specified as generic type parameters.
  • ISubscribeTo: Defines methods that enable the simple usage of topics and message factories.
  • IPublishTo: Defines methods that enable the simple usage of topics and message processors.
  • IMessageBroker: Defines methods for the management of Topics and subscriptions.
Providers
  • IProvider: Basic provider interface that defined methods for adding the actual workflow context to a given provider.
  • IConditionProvider: Extends the IProvider, enables the user to provide dynamically calculated conditions for loops and conditional statements.
  • IIterableProvider: Extends the IProvider, enables the user to provide IIterable objects for 'foreach' loops.
  • IIterationNumber: Extends the IProvider, enables the user to dynamically calculate the number of iterations a 'for' loop does.

Classes

  • TransformationChain: Implements the ICompositeStep and the MWE2 IWorkFlowComponent interface. As it is a composite step, it can contain additional transformation steps. In its execute method, the registered transformation steps are initialized and executed.
  • TransformationStep:Abstract class that implements the ITransformationStep interface, that acts as a base class for user defined transformation steps. It incorporates the following features:
    • Support for containing ISubscribeTo and IPublishTo objects
    • Initialize the context attribute in the initialize() method
    • Process all incoming messages
    • Support the addition of user defined initialization, execute functionality and message publication (doInitialize(), doExecute(), publishMessages())
  • MessageBroker: The MessageBroker is a singleton class that manages topics and subscriptions. It enables transformation steps to subscribe to topics, send and query messages, as well as acknowledge message processing (In case the message is successfully processed, the message itself will be removed from the topic's appropriate queue).
  • Topic: Topics contain subscribing transformation steps and messages sent to these subscribers. Messages are contained in a multi map whose key objects are transformation steps, while the value objects are lists of messages.
  • SubscribeTo: SubscribeTo objects contain an IMessageProcessor implementation and specify the Topic to which the transformation step has subscribed. The event processor is used for processing the messages that are provided by the topic. This ISubscribeTo implementation also features the priority property, which help in defining an order in which conflicting channels can be processed.
  • PublishTo: As specified in the IPublishTo interface, instances of this class contain an IMessageFactory object and the qualified name of a topic. The message factory is responsible for adding events to the aforementioned topic. The PublishTo class provides an easy to use interface for adding publishing messages.
Control Structures
  • Sequence:Composite transformation step that implements a basic sequence control flow construction. It initializes and executes its contained steps in the same sequence they have been defined.
  • Conditional: Composite transformation step that implements an 'IF' style conditional construction. The condition is specified by an IConditionProvider which enables the specification of dynamically evaluated conditions. If the condition evaluation returns true, the ifTrue step is executed, if otherwise, the ifFalse step is executed. As the condition is evaluated in run time, both of the steps is initialized.
  • ForLoop: Composite transformation step that implements a 'for' style loop. The number of iterations can either be explicitly specified at compile time, using the iterations attribute, or dynamically calculated by an IIterationNumberProvider.
  • ForeachLoop: Composite transformation step that implements a 'foreach' style loop. This kind of loop requires an IIterable object to iterate through. It is provided in run time by an IIterableProvider.
  • WhileLoop: Composite transformation step that implements a 'while' style loop. similar to the conditional step, the dynamically evaluated loop condition is provided by an IConditionProvider. The condition is evaluated before the current iteration.
  • DoWhileLoop: Composite transformation step that implements a 'do..while' style loop. similar to the while loop, the dynamically evaluated loop condition is provided by an IConditionProvider. In this case however, the condition is evaluated after the current iteration instead.
  • Parallel: Composite transformation step that enables the parallel execution of transformation steps. Each transformation step will be assigned to a new thread.
    • Be advised: The parallel regions should be independent from each other, as there is no order of execution defined. This means, that typically parallel regions should not send each other parametric messages.
Provider Implementations
  • BaseProvider: Abstract base provider implementation that has an IWorkFlowContext attribute. This way inheriting classes can access the workflow context.
  • BaseIterationNumberProvider: Basic iteration number provider that extend the BaseProvider abstract class and returns the number handed to it in its constructor.
Example Messages, Factories and Processors
  • StringMessage: Basic message implementation that has a String typed parameter. It serves as a basic example for implementing custom messages.
  • StringMessageFactory: Message Factory that is responsible for the creation of StringMessage objects. Similar to the StringMessage class, this class serves as an example.
  • StringMessageProcessor: Message Processor that is responsible for processing StringMessage objects. It serves as an example for user defined message processors.


Examples

All of the below stated examples can be found in the mwe2integration.examples project in the following repository:

Basics

Typically the following steps are needed to create an MWE Transformation Chain:

  • Create a new Eclipse plug-in project via File Menu --> New --> Project
  • Create a new MWE2 file (in a not default package) using the similar method. If prompted, add the Xtext nature to the project.
  • Define custom transformation steps, messages and other classes supporting them.
  • Define workflow structure in the MWE2 file
  • Run the MWE2 workflow or integrate it in the transformation architecture.

Simple Example

The usage of these classes can be most effectively described via a simple 'Hello World' example that defines two very simple transformation steps. These transformation steps do not communicate with each other using messages, and no complex control structures are used.

Define Transformation Steps

In the following step define two very simple transformation steps. Add these classes to the package created before.

ExampleATransformationStep.java

/** 
 * An example transformation step. User defined transformation steps should extend the abstract class 
 * TransformationStep. It already implements the core features of transformation steps, namely the management of 
 * publishings, subscriptions, as well as message processing and -creation.
 * 
 */
class ExampleATransformationStep extends TransformationStep {
	override doInitialize(IWorkflowContext ctx) {
		//this method is called after the workflow context is assigned to the step
		//The transformation should be  initialized here
		System.out.println("Init A transformation")
		//The context can be used to access global variables
		//via ctx.get("String")
	}
 
	override void doExecute() {
		//This method is executed during the execute method of a given transformation step,
		//after the received messages are processed and before outgoing messages are sent-
		//Run the transformation (or any other user defined function) here 
		System.out.println("A transformation executed")
	}
 
	override void dispose() {
		// Dispose functions
		System.out.println("Dispose A transformation")
	}
 
	//In this method the sending of messages can be defined
	//Typically the following implementation, which sends a given message type to all publishing topics, 
	//is sufficient
	override void publishMessages() {
		publishings.forEach[
			publishMessage("MESSAGE A")
		]
	}
}

ExampleBTransformationStep.java

/** 
 * An example transformation step. User defined transformation steps should extend the abstract class 
 * TransformationStep. It already implements the core features of transformation steps, namely the management of 
 * publishings, subscriptions, as well as message processing and -creation.
 * 
 * This class is the same as the A variant, it is needed as most of the examples call for two different 
 * transformation steps
 */
class ExampleBTransformationStep extends TransformationStep {
	override doInitialize(IWorkflowContext ctx) {
		//this method is called after the workflow context is assigned to the step
		//The transformation should be  initialized here
		System.out.println("Init B transformation")
		//The context can be used to access global variables
		//via ctx.get("String")
	}
 
	override void doExecute() {
		//This method is executed during the execute method of a given transformation step,
		//after the received messages are processed and before outgoing messages are sent-
		//Run the transformation (or any other user defined function) here 
		System.out.println("B transformation executed")
	}
 
	override void dispose() {
		// Dispose functions
		System.out.println("Dispose B transformation")
	}
 
	//In this method the sending of messages can be defined
	//Typically the following implementation, which send a given message type to all publishing topics, 
	//is sufficient
	override void publishMessages() {
		publishings.forEach[
			publishMessage("MESSAGE B")
		]
	}
}

Define Transformation Structure

Define the transformation chain structure using the MWE2 language. Make sure to include all the referenced packages (if the classes are in the same package as the MWE2 file, include that package as well), and that the module name should match the containing package as well.

SimpleChainExample.mwe2

module org.eclipse.viatra.emf.mwe2integration.example.SimpleChainExample
 
//Import the necessary libraries
//Note, that the package containing the workflow needs to be imported as well (if it contains used resources)
import org.eclipse.viatra.emf.mwe2integration.*
import org.eclipse.viatra.emf.mwe2integration.mwe2impl.*
import org.eclipse.viatra.emf.mwe2integration.mwe2impl.messages.*
import org.eclipse.viatra.emf.mwe2integration.examples.resources.*
 
//The workflow and components are defined in the usual MWE2 fashion
Workflow {
	//Add a TransformationChain component
	//This component represents an MWE2 component that can contain numerous transformations
	component = TransformationChain {
		//Add transformation steps
		//These classes all extend the TransformationStep abstract class, which implements their core features.
		//User defined functionality can be added via overriding the doExecute() method 
		step = ExampleATransformationStep{}
		//Multiple transformation steps will be executed in order of their definition
		//Note that in the other examples, more elaborate control constructions will be presented.
		step = ExampleBTransformationStep{}
	}
	//You can add additional regular MWE2 components here
}

After this, run the MWE2 file as an MWE 2 workflow. TODO finish

Simple Example with Conditional

Simple Example with Loops

Complex Example with Messaging

Complex Example with Parallel Execution

Complex Example (CPS)

A more complex example can be found in the IncQuery CPS example project: https://github.com/IncQueryLabs/incquery-examples-cps/wiki. The project itself aims at providing an example, how EMF IncQuery related technologies can be used in a model driven development workflow.

Naturally, this example contains numerous different transformation methods and other auxiliary steps. The VIATRA MWE2 integration library can be used to define the structure of these transformation steps. The example project at https://github.com/lunkpeter/incquery-examples-cps/tree/MWE/addons/org.eclipse.incquery.examples.cps.mwe2integration.example contains both batch- and fine-grained, event-driven M2M transformations. In this section, a VIATRA based event driven M2M transformation will be used.

MWE Workflow Components

  • Initializer component: This standard MWE 2 workflow component is responsible for the initialization of the transformation environment. It creates the model resources, generates the source model, instantiates the main IncQuery engine used by the transformation steps and creates the output project structure. It also adds the created resources to the workflow context.

Transformation Steps

The transformation step contains the following attributes:

    protected MWE2ControllableExecutor executor; //Executor that implements the IControllable interface. Responsible for controlling the ED transformation.
    protected AdvancedIncQueryEngine engine;     //Main IncQuery engine used by the transformation steps.
    protected CPS2DeploymentTransformationViatra transformation;   //The previously mentioned VIATRA based event-driven transformation.

It overrides the following methods:

    @Override
    public void initialize(IWorkflowContext ctx) {
        //store the context
        this.context = ctx;
        //get the input model from the Workflow context (it was added by the initializer)
        CPSToDeployment cps2dep = (CPSToDeployment) ctx.get("model");
        //get the main IncQuery engine from the Workflow context (it was added by the initializer)
        engine = (AdvancedIncQueryEngine) ctx.get("engine");
        //create the EVM Executor that controls the transformation
        executor = new MWE2ControllableExecutor(IncQueryEventRealm.create(engine));
        transformation = new CPS2DeploymentTransformationViatra();
        //Initialize the transformation using the controller Executor
        transformation.setExecutor(executor);
        transformation.initialize(cps2dep, engine);
        System.out.println("Initialized model-to-model transformation");
    }
 
    @Override
    public void execute() {
        //Process one incoming event
        processNextEvent();
        //Command the event-driven transformation to run
        executor.run();
        //Wait for the event-driven transformation
        while (!executor.isFinished()) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
 
        System.out.println("Model-to-model transformation executed");
        //Send events to all target channels
        sendEventToAllTargets();
    }
 
    @Override
    public void dispose() {
        //At the end of the workflow, stop the the Thread the transformation step is checking for new events and dispose the transformation itself
        isRunning = false;
        transformation.dispose();
        System.out.println("Disposed model-to-model transformation");
    }
  • Change Monitor Transformation Step: This step detects the changes in the intermediary deployment model, and sends the changes themselves to the M2T transformation step.

The transformation step contains the following attributes:

    protected AdvancedIncQueryEngine engine;     //Main IncQuery engine used by the transformation steps.
    protected DeploymentChangeMonitor monitor;   //A Change monitor class that collects all the changes in a specified deployment model, for a period of time.

It overrides the following methods:

    @Override
    public void initialize(IWorkflowContext ctx) {
        //store the context
        this.context = ctx;
        //get the main IncQuery engine from the Workflow context (it was added by the initializer)
        engine = (AdvancedIncQueryEngine) ctx.get("engine");
        //Get the deployment model root from the workflow context
        Deployment deployment = ((CPSToDeployment) ctx.get("model")).getDeployment();
        //Initialize monitor and start monitoring.
        monitor = new DeploymentChangeMonitor(deployment, engine);
        try {
            monitor.startMonitoring();
        } catch (IncQueryException e) {
            e.printStackTrace();
        }
    }
 
    @Override
    public void execute() {
        //Process one incoming event
        processNextEvent();
        //Create a new checkpoint that contains all the model changes since the previous checkpoint up to the current time.
        DeploymentChangeDelta delta = monitor.createCheckpoint();
        System.out.println("Checkpoint created");
        //Send the model changes to all target channels
        sendEventToAllTargets(delta);
    }
 
    @Override
    public void dispose() {
        //At the end of the workflow, stop the the Thread the transformation step is checking for new events
        isRunning = false;
        System.out.println("Disposed change monitor");
    }
  • M2T Transformation Step: The M2T transformation step uses a distributed code generator component that returns the output files as character sequences.

The transformation step contains the following attributes:

    protected AdvancedIncQueryEngine engine; 
    public ICPSGenerator generator;    //Code Generator component
    public String projectName;         //Name of the output project
    public String sourceFolder;        //Location of the output project
    public List<M2TOutputRecord> output;  //Output of the transformation
    public DeploymentChangeDelta delta;   //Incoming delta

It overrides the following methods:

    @Override
    public void initialize(IWorkflowContext ctx) {
        //store the context
        this.context = ctx;
        //get the main IncQuery engine from the Workflow context (it was added by the initializer)
        engine = (AdvancedIncQueryEngine) ctx.get("engine");
        //get the output project name from the Workflow context (it was added by the initializer)
        projectName = (String) ctx.get("projectname");
        //get the output project folder from the Workflow context (it was added by the initializer)
        sourceFolder = (String) ctx.get("folder");
        //Create new code generator
        generator = new CodeGenerator(projectName,engine,true);
    }
 
    @Override
    public void execute() {
        processNextEvent();
 
        ChangeM2TOutputProvider provider = new ChangeM2TOutputProvider(delta, generator, sourceFolder);
        output = provider.generateChanges();
 
        System.out.println("Model-to-text transformation executed");
        //Send output to serializer
        sendEventToAllTargets(output);
    }
 
    @Override
    public void dispose() {
        //At the end of the workflow, stop the the Thread in which the transformation step is checking for new events
        isRunning = false;
        System.out.println("Disposed model-to-text transformation");
    }
  • Serializer Transformation Step: Creates new source files based on the output provided by the M2T transformation.

The transformation step contains the following attributes:

    private boolean firstRun = true; //If the serializer is run for the first time, it sends events to the Model modification step, otherwise quits the workflow.
    public DefaultSerializer serializer; //CPS serializer
    public String sourceFolder;          //Location of the source folder
    public List<M2TOutputRecord> m2tOutput; //Output created by the M2T transformation

It overrides the following methods:

    @Override
    public void initialize(IWorkflowContext ctx) {
        this.context = ctx;
        //Init serializer
        System.out.println("Initialized serializer");
        serializer = new DefaultSerializer();
        sourceFolder = (String) ctx.get("folder");
 
    }
 
    @Override
    public void execute() {
        processNextEvent();
        //Serialize output
        ListBasedOutputProvider provider = new ListBasedOutputProvider(m2tOutput);
        serializer.serialize(sourceFolder, provider, new JavaIOBasedFileAccessor());
 
        System.out.println("Serialization completed");
        //If the serializer is run for the first time, it sends events to the Model modification step, otherwise quits the workflow.
        if(firstRun){
            getModifierChannel().createEvent();
            firstRun = false;
        } else {          
            getChainEndChannel().createEvent();
        }  
    }
 
    @Override
    public void dispose() {
        isRunning = false;
        System.out.println("Disposed serializer");
    }


  • Model Modifier Transformation Step: Modifies the source CPS model and sends events to the M2M transformation, meaning that the workflow has restarted.

The transformation step contains the following attributes:

    protected CPSToDeployment model; //Model root
    protected CPSModelBuilderUtil modelBuilder = new CPSModelBuilderUtil(); //CPS model modification utility class

It overrides the following methods:

    @Override
    public void initialize(IWorkflowContext ctx) {
        //receive the model root from the context
        model = (CPSToDeployment) ctx.get("model");  
    }
 
    @Override
    public void execute() {
        processNextEvent();
        //modify model
        modifyModel();
        System.out.println("Model modification executed");
        sendEventToAllTargets();
 
    }
 
    @Override
    public void dispose() {
        isRunning = false;
        System.out.println("Disposed model modifier");
    }

Events, Event Factories, Processors

  • ChangeDeltaEvent: Event type that contains the model modifications detected by a DeploymentChangeMonitor.
  • M2TOutputEvent: Event Type that contains character sequences created by the M2T transformation.
  • ChangeDeltaEventFactory: Event factory that creates a ChangeDeltaEvent.
  • M2TOutputEventFactory: Event factory that creates a M2TOutputEvent.
  • ChangeDeltaEventProcessor: Event processor that adds the ChangeDelta contained by a ChangeDeltaEvent to its parent Transformation Step.
  • M2TOutputEventProcessor: Event processor that adds the M2T output character sequences contained by a M2TOutputEvent to its parent Transformation Step.


Workflow Structure

The structure of the workflow is specified in the ControllableEventDrivenTransformation.mwe2 file. After the previously defined transformation steps and workflow components have been imported to the module, they can be easily instantiated using the MWE2 description language. Note, that the package containing the .mwe2 file should be imported as well.

module org.eclipse.viatra.emf.mwe2integration.transdemo
 
import org.eclipse.viatra.emf.mwe2integration.*
import org.eclipse.viatra.emf.mwe2integration.mwe2impl.*
import org.eclipse.incquery.examples.cps.integration.*
import org.eclipse.incquery.examples.cps.integration.events.*
import org.eclipse.incquery.examples.cps.integration.eventdriven.controllable.*
 
//Define Channels here
var chainStartChannel = MWE2Channel {}
var chainEndChannel = MWE2Channel {}
 
var M2MChannel = MWE2Channel {}
var ChangeMonitorChannel = MWE2Channel {}
var M2TChannel = MWE2Channel {}
var SerializerChannel = MWE2Channel {}
var ModifierChannel = MWE2Channel {}
 
Workflow {
        //Add initializer workflow component
	component = InitializerComponent{
                //Set the seed and model size for model generation
		seed = "11111"
		modelSize = "4"
                //Define location for model resource
		modelDir = "D:\\MWE_TEST\\model"
		modelName = "MWE_TEST"
                //Define output project location and name
		outputProjectLocation = "D:\\MWE_TEST"
		outputProjectName = "VIATRA_ED_Controllable"
	}
	//Use the MWE2TransformationChain class for defining transformation chains
	component = MWE2TransformationChain {
                //Define the start and end channels of the transformation chain
		startChannel = MWE2TargetChannel{channel = chainStartChannel}
		endChannel = MWE2ListeningChannel{channel = chainEndChannel}
 
                //Add an event driven viatra transformation step that listens to the chainStartChannel and the m2mChannel
                //It targets the change monitor
		transformationStep = M2MControllableEventDrivenViatraTransformationStep {
			chainStartChannel = MWE2ListeningChannel{channel = chainStartChannel}
			m2MChannel = MWE2ListeningChannel{channel = M2MChannel}
			changeMonitorChannel = MWE2TargetChannel{channel = ChangeMonitorChannel}
		}
 
                //Create a change monitor transformation step
                //Add a ChangeDeltaEventFactory to its target channel
		transformationStep = ChangeMonitorTransformationStep{
			changeMonitorChannel = MWE2ListeningChannel{channel = ChangeMonitorChannel}
			m2TChannel = MWE2TargetChannel{channel = M2TChannel factory = ChangeDeltaEventFactory{}}
		}
 
                //Create a M2t transformation step
                //Add a ChangeDeltaEventProcessor to its listening channel
                //Add a M2TOutputEventFactoryto its target channel
		transformationStep = M2TDistributedTransformationStep {
			m2TChannel = MWE2ListeningChannel{channel = M2TChannel processor = ChangeDeltaEventProcessor{}}
			serializerChannel = MWE2TargetChannel{channel = SerializerChannel factory = M2TOutputEventFactory{}}			
		}
 
                //Create a serializer transformation step
                //Add a M2TOutputEventProcessor to its listening channel
                //Define both chainEndChannel and ModifierChannel as target channels (the workflow will quit after two cycles)
		transformationStep = SerializerTransformationStep{
			serializerChannel = MWE2ListeningChannel{channel = SerializerChannel processor = M2TOutputEventProcessor{}}
			chainEndChannel = MWE2TargetChannel{channel = chainEndChannel}
			modifierChannel = MWE2TargetChannel{channel = ModifierChannel}
		}
 
                //Create a serializer transformation step
                //Define both m2MChannel as target channel
		transformationStep = ModelModifierStep{
			modifierChannel = MWE2ListeningChannel{channel = ModifierChannel}
			m2MChannel = MWE2TargetChannel{channel = M2MChannel}
		}
	}
 
}

Execution

To run the specified workflow, simply run the mwe2 file as an 'MWE2 Workflow'.

Advanced Features

Wrapping fine grained event-driven transformations

  • IController: An interface that defines methods for explicitly controlling the execution of a fine-grained event-driven model transformation step.
  • IEnabler: Interface that defines methods that can enable and disable a fine-grained, event-driven event driven transformation step.
  • ISchedulerController: Interface that defines functions which are used when an IController object also wraps an IncQuery EVM Scheduler.
  • MWE2ControllableExecutor: An IncQuery EVM Executor, that enables the MWE 2 workflow to control any IncQuery EVM based fine-grained event-driven transformation, provided that the transformation's ExecutionSchema is created with this executor. It also implements the IController interface which enables the workflow to explicitly start the execution of the transformation. The MWE2ControllableExecutor also provides information about the state of the transformation (i.e.: if the transformation has reached a steady state or not).
  • MWE2EnablerExecutor: An IncQuery EVM Executor, that enables the MWE 2 workflow to control any EVM based fine-grained event-driven transformation, provided that the transformation's ExecutionSchema is created with this executor. It also implements the IEnabler interface which means that based on the state of other transformation steps, the event-driven transformation can be enabled or disabled.
  • MWE2BaseControllableScheduler: An EVM scheduler that enables the workflow to explicitly control the execution of a fine-grained event-driven transformation. As it implements the IController interface, its usage is similar to the MWE2ControllableExecutor. Internally, however, this solution uses a custom Scheduler object instead of an Executor. Using a custom Scheduler means, that the original IncQuery EVM Scheduler will be overridden.

Detailed information about the usage of these classes can be found in the CPS example.

Project Locations

The library itself can be found at https://github.com/lunkpeter/org.eclipse.viatra/tree/MWE/plugins/org.eclipse.viatra.emf.mwe2integration. The test project at https://github.com/lunkpeter/org.eclipse.viatra/tree/MWE/tests/org.eclipse.viatra.emf.mwe2integration.test contains a simple example as well. Note that at its current state, the library itself is not an integrated part of the VIATRA framework, however as this inclusion is intended in the future, the library is in the org.eclipse.viatra namespace.

Copyright © Eclipse Foundation, Inc. All Rights Reserved.