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/Transformation/Adapter Framework/Adapter Implementations"

(Created page with "== Motivation == The development and debugging of reactive event-driven model transformations is not a trivial exercise, the basic concepts of software debugging however can...")
 
Line 1: Line 1:
== Motivation ==
 
 
The development and debugging of reactive event-driven model transformations is not a trivial exercise, the basic concepts of software debugging however can be mapped to the field of  model transformations. Debuggers can be used for detecting bugs, as well as better understanding the structure and behavior of programs. Direct control over a program allows the programmer to follow the flow of execution or stop the program at any desired point. Then it is possible to inspect its current state and verify the correctness of the software. These properties are very desirable in the field of model transformations as well. The VIATRA framework possesses a solution for implementing transformation debugging related functionalities.
 
 
 
A full featured transformation debugger requires a software solution that is able to observe and control VIATRA-based model transformations. Such an extension is able to insert additional functionality into certain points during model transformations. The transformation adapter framework allows the definition of additional functionalities that are executed at certain points in event-driven model transformations, without altering the behavior of the original transformation itself. The previously described debug functionalities are implemented using the transformation adapter framework.
 
 
== High level architecture==
 
[[File:VIATRA_adapter_arch.png]]
 
 
=== Components ===
 
*  '''Adapter Interface''': The Adapter Interface defines a set of callback methods that are executed at certain points during the transformation execution. A number of Adapters can implement this interface, in order to define additional functionality that should be undertaken at certain points in the transformation.
 
*  '''Adaptable Executor''': VIATRA Executors are responsible for executing model transformation rule actions provided by rule activations. The adaptable executor extends these default executors, and allows the transformation developer to register a number of adapter in-stances and calls the appropriate callback method of each adapter at certain points during execution. These Adaptable Executor instances are added to VIATRA event-driven trans-formations, which only utilizes their EVM Executor interface. This means, that this adapter-based implementation is completely transparent towards the transformation code, and the internal VIATRA components as well.
 
*  '''Adaptable Executor Factory''': Responsible for creating adaptable executors
 
*  '''Adapter Configuration''': The adapter configurations serve multiple purposes. They can either define dependency relations between adapter implementations, or specify complex use cases which requires more than one adapter to function properly
 
 
== Adapter implementations ==
 
 
 
The VIATRA transformation adapter framework contains a number of default adapter implementations, that realize model transformation debugging use cases. the default set of adapters consist of the following:
 
The VIATRA transformation adapter framework contains a number of default adapter implementations, that realize model transformation debugging use cases. the default set of adapters consist of the following:
  
=== Debug adapter ===
+
== Debug adapter ==
The debug adapter implements a breakpoint based debugging approach (similar to JDT). It contains the logic for stopping the transformation execution if a breakpoint condition matches, and ordering the UI to display the program context.To support various debugging use cases, the debugger can be configured with different user interface and breakpoint implementations.
+
The VIATRA transformation debugger implements a breakpoint based debugging approach (similar to JDT). It contains the logic for stopping the transformation execution if a breakpoint condition matches, and ordering the UI to display the program context.To support various debugging use cases, the debugger can be configured with different user interface and breakpoint implementations. in order to implement this funfctionality, the debugger uses the components depicted on the figure below.
  
 
[[File:debug_adapter.png]]
 
[[File:debug_adapter.png]]
  
* '''Debugger UI''': Responsible for displaying the internal state of the event-driven model transformation in progress, and it allows the transformation developer to manipulate the execution sequence. Using this component enables the transformation debugger component to remain UI independent, and support the definition of custom user interface implementations.
+
* '''Transformation Debug Listener''': Repsonsible for displaying the state of the VIATRA transformation using a specific Debugger UI.
** '''Console Debugger UI''': This default UI implementation uses the standard input and output in order to communicate with the transformation developer.
+
* '''Transformation Debug Adapter''': Responsible for halting the execution of the transformation if a breakpoint is reached. Once the breakpoint is encountered, it allows the user to select the next action to be taken via the Debugger UI.
** '''VIATRA Viewers Debugger UI''': In this case the VIATRA  Viewers framework is utilized to visualize the target and source model state via using annotated VIATRA queries.
+
* '''Debugger UI''': Responsible for displaying the internal state of the model transformation in progress, and it allows the transformation developer to manipulate the execution sequence. Using this component enables the transformation debugger component to remain UI independent, and support the definition of custom user interface implementations.
 +
  * '''Console Debugger UI''': This default UI implementation uses the standard input and output in order to communicate with the transformation developer.
 +
  * '''VIATRA Viewers Debugger UI''': In this case the VIATRA  Viewers framework is utilized to visualize the target and source model state via using annotated VIATRA queries.
 
* '''Breakpoints''': Each breakpoint realization compares a given activation to a set of constraints. If the constraints match, the debugger is informed that it should halt the execution of the transformation, and wait for a response from the transformation developer.
 
* '''Breakpoints''': Each breakpoint realization compares a given activation to a set of constraints. If the constraints match, the debugger is informed that it should halt the execution of the transformation, and wait for a response from the transformation developer.
** '''Rule Activation Breakpoints''': Contains references to a transformation rule, a lifecycle state, and a set of source model elements that have triggered the activation. This way the debugger can check if the activation being fired has a breakpoint attached to it or not.
+
  * '''Rule Activation Breakpoints''': Contains references to a transformation rule, a lifecycle state, and a set of source model elements that have triggered the activation. This way the debugger can check if the activation being fired has a breakpoint attached to it or not.
* '''Conditional Breakpoints''': These breakpoints are able to define global constraints that are not only affected by the current activation. A similar concept is available in the Eclipse Java Development Tools (JDT). The constraints are defined by using the VIATRA query language.
+
  * '''Conditional Breakpoints''': These breakpoints are able to define global constraints that are not only affected by the current activation. A similar concept is available in the Eclipse Java Development Tools (JDT). The constraints are defined by using the VIATRA query language.
 +
* '''Transformation Debugger Configuration''': This configuration binds the transformation debug adapter and listenercomponents together and allows a more straightforward usage.
  
=== Manual conflict resolver adapter ===
+
== Manual conflict resolver adapter ==
  
 
This adapter allows the transformation developer to manually override the execution order of transformation rule activations. Particularly useful during debugging, as allows the easy reproduction of bugs, which require a certain firing order. It uses the similar interchangeable Debugger UI component as the Debug adapter.
 
This adapter allows the transformation developer to manually override the execution order of transformation rule activations. Particularly useful during debugging, as allows the easy reproduction of bugs, which require a certain firing order. It uses the similar interchangeable Debugger UI component as the Debug adapter.
Line 37: Line 22:
 
[[File:mc_adapter.png]]
 
[[File:mc_adapter.png]]
  
=== Trace coder Adapter ===
+
== Trace coder Adapter ==
  
The transformation debug adapter implements a transformation debugger that follows the breakpoint-based approach. However, the execution sequence of VIATRA-based event-driven model transformations is typically non-deterministic. The trace coder adapter is responsible for logging the transformation execution sequence (i.e.: order of transformation rule activation firings). This *transformation trace* can later be analyzed or used during re-execution of the transformation.
+
The transformation debug configuration contains a transformation debugger that follows the breakpoint-based approach. However, the execution sequence of VIATRA-based event-driven model transformations is typically non-deterministic. The trace coder is responsible for logging the transformation execution sequence (i.e.: order of transformation rule activation firings). This *transformation trace* can later be analyzed or used during re-execution of the transformation.
  
Transformation traces are hierarchical object structures aiming at storing transformation execution sequences. Transformation traces consist of activation and rule parameter traces. Activation traces identify the fired rule, and rule parameter traces specify which elements have triggered the execution of the given rule. Based on this information, the transformation can be re-executed for further evaluation, or erroneous rules can be detected during post-mortem analysis.
+
Transformation traces are hierarchical object structures aiming at storing transformation execution sequences. Transformation traces consist of activation and rule parameter traces. Activation traces identify the fired rule, and rule parameter traces specify which elements have triggered the execution of the given rule. Based on this information, the transformation can be re-executed for further evaluation, or erroneous rules can be detected during post mortem analysis.
  
Similar to the previously introduced adapters, the trace coder adapter utilizes interchangeable sub-components:
+
Similar to the previously introduced components, the trace coder listener utilizes interchangeable subcomponents:
  
 
[[File:coder_adapter.png]]
 
[[File:coder_adapter.png]]
Line 50: Line 35:
 
* '''Trace model serializer''': Responsible for saving and loading trace models
 
* '''Trace model serializer''': Responsible for saving and loading trace models
  
=== Trace Executor adapter ===
+
== Trace Executor adapter ==
  
 
This adapter is responsible for re-executing a transformation sequence recorded by the trace coder adapter. Particularly useful during debugging, as it allows the determinization of the otherwise random execution sequence of VIATRA event-driven transformations.  
 
This adapter is responsible for re-executing a transformation sequence recorded by the trace coder adapter. Particularly useful during debugging, as it allows the determinization of the otherwise random execution sequence of VIATRA event-driven transformations.  
Line 65: Line 50:
 
* Also keep in mind that the trace executor needs an already existing transformation trace, hence it should not be used simultaneously with the trace coder.
 
* Also keep in mind that the trace executor needs an already existing transformation trace, hence it should not be used simultaneously with the trace coder.
  
== Usage Examples TODO ==
+
== Usage Examples ==
 +
 
 +
Adapters and listeners can be added to new or already existing VIATRA transformations in a simple and straightforward fashion. The VIATRA transformation API allows the transformation developer to attach these adapters and listeners directly to the model transformation, without needing to alter the transformation code itself. The transformation API classes create a modified, adapter supporting background structure, however this step is completely transparent to the transformation developer. Both Batch and event driven VIATRA transformations are supported, and will be presented in this section. The example shown here uses the VIATRA CPS example model transformations, to emphasize, that adding adapters does not require any change in the transformation code.
 +
 
 +
=== Adding adapters to a VIATRA transformation===
 +
 
 +
Note that these examples only show the method for adding adapters to VIATRA transformations. The Adapters used in these examples will not work if used all together (especially true to the trace coder and executor components). In order to ensure that the adapters do not have adverse effects on each other use the predefined adapter configurations or individual adapters.
 +
 
 +
==== Batch Transformation ===
 +
<source lang="java">
 +
transformation = BatchTransformation.forEngine(engine)
 +
    //Create a debug adapter
 +
    //The debugger implements a classic breakpoint based functionality mapped to the field of model transformations.
 +
    //Similar to the Java debugger --> Statements == transformation rule activations.
 +
    //Breakpoints can be rendered to the individual transformation rule activations, or global conditions.
 +
    //During the execution: if a breakpoint activation is about to be fired, or the global condition is met, the execution of the transformation is halted.
 +
    //At this point, the user can specify the next course of action: step to the next activation firing, or continue the execution till the next breakpoint.
 +
    .addAdapterConfiguration(
 +
        new TransformationDebuggerConfiguration(
 +
            //By default the adapter uses the default console based UI (if no other debug controller is specified)
 +
            //In this case the VIATRA  Viewers based debugger UI is utilized
 +
            //It allows the debugger go visualize the target and source model state via using annotated VIATRA queries
 +
            new ViewersDebugger(engine, ViewersPatterns.instance.specifications),
 +
            //Traditional breakpoints can be attached to given rules, or rule activations. This way if a given activation, or an activation of a rule is about to be fired, the execution will be halted.
 +
            //Transformation execution is halted once a Host rule activation is about to be fired.
 +
            new TransformationBreakpoint(hostRule.ruleSpecification),
 +
            //Conditional breakpoints contain VIATRA query specifications --> can define global conditions regarding either source or target models.
 +
            //Transformation execution is halted if there are 2 application instances in the source model
 +
            new ConditionalTransformationBreakpoint(engine, patterns.getApplicationInstance(engine).specification, 2)
 +
            )
 +
       
 +
    )
 +
   
 +
    //Create trace coder listener
 +
    //This listener is responsible for storing the transformation execution sequence (i.e.: order of transformation rule activation firings)
 +
    //This transformation trace can later be analyzed or used during re-execution
 +
    //Transformation trace --> hierarchical object structure --> aiming at storing a transformation execution sequence.
 +
    //Consists of Activation and rule parameter traces --> activation traces identify the fired rule, and specify which elements have triggered the execution of the given rule.
 +
    .addListener( new TraceCoder(URI.createURI("transformationtrace/batchtrace.transformationtrace")))
 +
   
 +
    //Create a manual conflict resolver adapter
 +
    //This adapter allows the transformation developer to manually override the execution order of transformation rule activations.
 +
    //Particularly useful during debugging, allows the easy reproduction of bugs, which require a certain firing order.
 +
    //Can be combined with the trace coder and executor --> erroneous execution sequence can be saved and re-executed numerous times
 +
    //Even transported between workstations (send to a co-worker for debugging)
 +
    .addAdapter(new ManualConflictResolver(new ConsoleDebugger))
 +
   
 +
    //Create trace executor adapter
 +
    //This adapter is responsible for re-executing a transformation sequence recorded by the trace coder adapter.
 +
    //Particularly useful during debugging, as it allows the determinization of the otherwise random execution sequence of VIATRA event-driven transformations.
 +
    //Note, that the usage of this adapter has a heavy effect on transformation performance, it is only advised to use it on small scale test models.
 +
    //Also keep in mind that the trace executor needs an already existing transformation trace, hence it should not be used simultaneously with the trace coder.
 +
    .addAdapter(new TraceExecutor(URI.createURI("transformationtrace/trace.transformationtrace")))
 +
   
 +
    //This listener implements a basic logging functionality
 +
    .addListener(new LoggingEVMListener(logger))
 +
    .build
 +
</source>
 +
 
 +
==== Event-driven Transformation ===
 +
<source lang="java">
 +
transformation = EventDrivenTransformation.forEngine(engine)
 +
    .setConflictResolver(createConflictResolver)
 +
    .addRule(hostRule)
 +
    .addRule(applicationRule)
 +
    .addAdapterConfiguration(
 +
        new TransformationDebuggerConfiguration(
 +
            new ViewersDebugger(engine, ViewersPatterns.instance.specifications),
 +
            new TransformationBreakpoint(hostRule.ruleSpecification),
 +
            new ConditionalTransformationBreakpoint(engine, patterns.getApplicationInstance(engine).specification, 2)))
 +
    .addListener( new TraceCoder(URI.createURI("transformationtrace/trace.transformationtrace")))
 +
    .addAdapter(new ManualConflictResolver(new ConsoleDebugger))
 +
    .addAdapter(new TraceExecutor(URI.createURI("transformationtrace/edtrace.transformationtrace")))
 +
    .addListener(new LoggingEVMListener(logger))
 +
    .build
 +
</source>

Revision as of 07:57, 1 April 2016

The VIATRA transformation adapter framework contains a number of default adapter implementations, that realize model transformation debugging use cases. the default set of adapters consist of the following:

Debug adapter

The VIATRA transformation debugger implements a breakpoint based debugging approach (similar to JDT). It contains the logic for stopping the transformation execution if a breakpoint condition matches, and ordering the UI to display the program context.To support various debugging use cases, the debugger can be configured with different user interface and breakpoint implementations. in order to implement this funfctionality, the debugger uses the components depicted on the figure below.

Debug adapter.png

  • Transformation Debug Listener: Repsonsible for displaying the state of the VIATRA transformation using a specific Debugger UI.
  • Transformation Debug Adapter: Responsible for halting the execution of the transformation if a breakpoint is reached. Once the breakpoint is encountered, it allows the user to select the next action to be taken via the Debugger UI.
  • Debugger UI: Responsible for displaying the internal state of the model transformation in progress, and it allows the transformation developer to manipulate the execution sequence. Using this component enables the transformation debugger component to remain UI independent, and support the definition of custom user interface implementations.
 * Console Debugger UI: This default UI implementation uses the standard input and output in order to communicate with the transformation developer.
 * VIATRA Viewers Debugger UI: In this case the VIATRA  Viewers framework is utilized to visualize the target and source model state via using annotated VIATRA queries.
  • Breakpoints: Each breakpoint realization compares a given activation to a set of constraints. If the constraints match, the debugger is informed that it should halt the execution of the transformation, and wait for a response from the transformation developer.
 * Rule Activation Breakpoints: Contains references to a transformation rule, a lifecycle state, and a set of source model elements that have triggered the activation. This way the debugger can check if the activation being fired has a breakpoint attached to it or not.
 * Conditional Breakpoints: These breakpoints are able to define global constraints that are not only affected by the current activation. A similar concept is available in the Eclipse Java Development Tools (JDT). The constraints are defined by using the VIATRA query language.
  • Transformation Debugger Configuration: This configuration binds the transformation debug adapter and listenercomponents together and allows a more straightforward usage.

Manual conflict resolver adapter

This adapter allows the transformation developer to manually override the execution order of transformation rule activations. Particularly useful during debugging, as allows the easy reproduction of bugs, which require a certain firing order. It uses the similar interchangeable Debugger UI component as the Debug adapter.

Mc adapter.png

Trace coder Adapter

The transformation debug configuration contains a transformation debugger that follows the breakpoint-based approach. However, the execution sequence of VIATRA-based event-driven model transformations is typically non-deterministic. The trace coder is responsible for logging the transformation execution sequence (i.e.: order of transformation rule activation firings). This *transformation trace* can later be analyzed or used during re-execution of the transformation.

Transformation traces are hierarchical object structures aiming at storing transformation execution sequences. Transformation traces consist of activation and rule parameter traces. Activation traces identify the fired rule, and rule parameter traces specify which elements have triggered the execution of the given rule. Based on this information, the transformation can be re-executed for further evaluation, or erroneous rules can be detected during post mortem analysis.

Similar to the previously introduced components, the trace coder listener utilizes interchangeable subcomponents:

Coder adapter.png

  • Activation coder: Creates Activation Trace objects, using the parameters extracted from the activation object.
  • Trace model serializer: Responsible for saving and loading trace models

Trace Executor adapter

This adapter is responsible for re-executing a transformation sequence recorded by the trace coder adapter. Particularly useful during debugging, as it allows the determinization of the otherwise random execution sequence of VIATRA event-driven transformations. It operates the following way: as the transformation is being executed, the activation at hand is compared to the upcoming entry in a previously loaded transformation trace. If the activation matches the trace record, it is executed, if not the executor finds the matching one.


Executor adapter.png


As seen here, the trace executor component utilizes the same sub-components as the trace coder.

Noteable information regarding the trace executor:

  • The usage of this adapter has a heavy effect on transformation performance, it is only advised to use it on small scale test models.
  • Also keep in mind that the trace executor needs an already existing transformation trace, hence it should not be used simultaneously with the trace coder.

Usage Examples

Adapters and listeners can be added to new or already existing VIATRA transformations in a simple and straightforward fashion. The VIATRA transformation API allows the transformation developer to attach these adapters and listeners directly to the model transformation, without needing to alter the transformation code itself. The transformation API classes create a modified, adapter supporting background structure, however this step is completely transparent to the transformation developer. Both Batch and event driven VIATRA transformations are supported, and will be presented in this section. The example shown here uses the VIATRA CPS example model transformations, to emphasize, that adding adapters does not require any change in the transformation code.

Adding adapters to a VIATRA transformation

Note that these examples only show the method for adding adapters to VIATRA transformations. The Adapters used in these examples will not work if used all together (especially true to the trace coder and executor components). In order to ensure that the adapters do not have adverse effects on each other use the predefined adapter configurations or individual adapters.

= Batch Transformation

transformation = BatchTransformation.forEngine(engine)
    //Create a debug adapter
    //The debugger implements a classic breakpoint based functionality mapped to the field of model transformations.
    //Similar to the Java debugger --> Statements == transformation rule activations.
    //Breakpoints can be rendered to the individual transformation rule activations, or global conditions.
    //During the execution: if a breakpoint activation is about to be fired, or the global condition is met, the execution of the transformation is halted.
    //At this point, the user can specify the next course of action: step to the next activation firing, or continue the execution till the next breakpoint.
    .addAdapterConfiguration(
        new TransformationDebuggerConfiguration(
            //By default the adapter uses the default console based UI (if no other debug controller is specified)
            //In this case the VIATRA  Viewers based debugger UI is utilized
            //It allows the debugger go visualize the target and source model state via using annotated VIATRA queries
            new ViewersDebugger(engine, ViewersPatterns.instance.specifications), 
            //Traditional breakpoints can be attached to given rules, or rule activations. This way if a given activation, or an activation of a rule is about to be fired, the execution will be halted.
            //Transformation execution is halted once a Host rule activation is about to be fired.
            new TransformationBreakpoint(hostRule.ruleSpecification),
            //Conditional breakpoints contain VIATRA query specifications --> can define global conditions regarding either source or target models.
            //Transformation execution is halted if there are 2 application instances in the source model 
            new ConditionalTransformationBreakpoint(engine, patterns.getApplicationInstance(engine).specification, 2)
            )
 
    )
 
    //Create trace coder listener
    //This listener is responsible for storing the transformation execution sequence (i.e.: order of transformation rule activation firings)
    //This transformation trace can later be analyzed or used during re-execution 
    //Transformation trace --> hierarchical object structure --> aiming at storing a transformation execution sequence.
    //Consists of Activation and rule parameter traces --> activation traces identify the fired rule, and specify which elements have triggered the execution of the given rule. 
    .addListener( new TraceCoder(URI.createURI("transformationtrace/batchtrace.transformationtrace")))
 
    //Create a manual conflict resolver adapter
    //This adapter allows the transformation developer to manually override the execution order of transformation rule activations.
    //Particularly useful during debugging, allows the easy reproduction of bugs, which require a certain firing order.
    //Can be combined with the trace coder and executor --> erroneous execution sequence can be saved and re-executed numerous times
    //Even transported between workstations (send to a co-worker for debugging)
    .addAdapter(new ManualConflictResolver(new ConsoleDebugger))
 
    //Create trace executor adapter
    //This adapter is responsible for re-executing a transformation sequence recorded by the trace coder adapter.
    //Particularly useful during debugging, as it allows the determinization of the otherwise random execution sequence of VIATRA event-driven transformations.
    //Note, that the usage of this adapter has a heavy effect on transformation performance, it is only advised to use it on small scale test models.
    //Also keep in mind that the trace executor needs an already existing transformation trace, hence it should not be used simultaneously with the trace coder.
    .addAdapter(new TraceExecutor(URI.createURI("transformationtrace/trace.transformationtrace")))
 
    //This listener implements a basic logging functionality
    .addListener(new LoggingEVMListener(logger))
    .build

= Event-driven Transformation

transformation = EventDrivenTransformation.forEngine(engine)
    .setConflictResolver(createConflictResolver)
    .addRule(hostRule)
    .addRule(applicationRule)
    .addAdapterConfiguration(
        new TransformationDebuggerConfiguration(
            new ViewersDebugger(engine, ViewersPatterns.instance.specifications), 
            new TransformationBreakpoint(hostRule.ruleSpecification),
            new ConditionalTransformationBreakpoint(engine, patterns.getApplicationInstance(engine).specification, 2)))
    .addListener( new TraceCoder(URI.createURI("transformationtrace/trace.transformationtrace")))
    .addAdapter(new ManualConflictResolver(new ConsoleDebugger))
    .addAdapter(new TraceExecutor(URI.createURI("transformationtrace/edtrace.transformationtrace")))
    .addListener(new LoggingEVMListener(logger))
    .build

Back to the top