• No results found

Runtime Environment and Transformation Structure

In this section, we introduce the structure of change-driven transformations that we generate from a response specification. We also explain the additional structures required for the integration of single responses intoChange2CommandTransformings, which we refer to as the runtime environment. Responses are transformed into such an environment.

We first introduce the general structure of a runtime environment and explain the purposes of special runtime data structures. Thereafter, we introduce the different elements of which the runtime environment consists and which are realizations of the response language concepts.

6.2.1 Structure of the Runtime Environment

As introduced in subsection 6.1.3, Vitruvius provides a transformation environment that relies on so calledChange2CommandTransformingelements. They manage the transforma-tions for a certain metamodel pair and transform given model changes into commands that execute the appropriate transformations.

The runtime environment for a specific set of transformations between two metamodels has to define aChange2CommandTransformingas the entry point to the transformations.

The elements and the structure of a runtime environment are explained on the exemplary environment shown in Figure 6.2.

A single transformation that is generated from a response specification is defined by an implementation of theResponseinterface, which provides a method for executing the trans-formation. Such a concrete transformation is represented by theConcreteResponseclass in our example. We separate repair routines from responses, as motivated in section 5.5. A repair routine is represented by an implementation of theRepairRoutineinterface, which provides a method for its execution. The example contains two concrete repair routines, which are theConcreteExplicitRepairRoutineand theConcreteImplicitRepairRoutine. A re-sponse implicitly defines a repair routine, which it executes after checking the trigger. In the example, theConcreteImplicitRepairRoutineimplements the implicit repair routine of theConcreteResponse.

6.2 Runtime Environment and Transformation Structure

Change2CommandTransforming ResponseExecutor Response

applyResponse(...)

ConcreteResponse RepairRoutine

applyRoutine()

ConcreteExplicitRepairRoutine ConcreteImplicitRepairRoutine RepairRoutinesFacade

callConcreteExplicitRepairRoutine(...)

1..* 1..*

1

Figure 6.2: Structure and dependencies in an exemplary runtime environment with one response and two repair routines

In contrast to an implicit repair routine, which is defined by each response and is only called by it, an explicit repair routine is supposed to be called by others. A facade class, in the example theRepairRoutineFacade, defines one method for each of the specified explicit repair routines. Such a method expects the model elements required by the related repair routine as parameters and delegates the call to a new instance of the repair routine by calling itsapplyRoutinemethod. In the example, the facade class only defines one method for theConcreteExplicitRepairRoutinebecause the other concrete repair routine is implicitly defined by the response and thus cannot be called by others.

For each set of transformations, later defined in one document of responses, the environ-ment contains one package for the responses and one for the repair routines. The repair routines package also provides a facade class for all of its repair routines. The responses package contains aResponseExecutor, which provides the access point to all responses.

The executor is responsible for executing appropriate responses for an atomic change. In turn, aChange2CommandTransforming, the entry point of the transformation environment, can consist of differentResponseExecutors, which it calls for all processed changes. The rationale for the separation of these two elements is explained later.

6.2.2 Runtime Data Structures

In addition to responses and repair routines, we use two further data structures in the runtime environment, the ResponseExecutionStateand the ResponseElementState. The ResponseExecutionStateencapsulates data for the execution of one response that is passed between the response and the repair routines. It consists of the correspondence model, an implementation of a user interaction interface as explained in subsection 5.7.3, and a so calledTransformationResult, which is required for defining the persistence of models.

The response language provides several constructs that define different modifications of model elements and their correspondences. Instead of generating code for these operations each time they are required, we encapsulate the functionality inResponseElementStates.

interface ResponseElementState { void preprocess();

void postprocess();

void addCorrespondingElement(EObject newCorrespondingElement, String tag);

void removeCorrespondingElement(EObject oldCorrespondingElement);

void delete();

}

Listing 6.1: The interface of aResponseElementState

Such a state is responsible for managing a single model element during the execution of a transformation. It is initialized with a model element and provides the operations for influencing its state according to the response language constructs, as shown in the interface specification in Listing 6.1.

AResponseElementStateprovides methods for specifying the correspondence addition or removal to another element and for marking the element to be deleted. The correspondence addition or removal produces the same result, no matter on which of the two elements it is performed. To perform these operations correctly, they are not executed immediately, but by calling thepreprocessandpostprocessmethods. The preprocessing has to be performed before, and the post-processing must be executed after calling the execution block. For example, correspondences have to be added after the operations of the execution blocks because the correspondences require the element TUIDs to be computable, which is usually not possible before setting the appropriate property values in the execution block.

All element states of a transformation are handled by aResponseElementStatesHandler. Its interface is presented in Listing 6.2. It provides methods for initializing the element states for created or retrieved elements. The distinction between created and retrieved elements is currently necessary because the modification of retrieved elements can in-fluence their TUIDs, which is automatically updated by the element state. The handler provides methods for the same operations as an element state and delegates their calls to the appropriate elements. Finally, pre- and post-processing methods are provided that execute those operations on all states.

The element states are responsible for TUID updates, which are automatically performed in the post-processing. Because of that update, the element states of all retrieved elements have to be initialized explicitly, even if none of their state changing operations are called.

interface ResponseElementStatesHandler {

void addCorrespondenceBetween(EObject firstElem, EObject secondElem, String tag);

void removeCorrespondenceBetween(EObject firstElem, EObject secondElem);

void deleteObject(EObject element);

void initializeCreateElementState(EObject element);

void initializeRetrieveElementState(EObject element);

void preprocessElementStates();

void postprocessElementStates();

}

Listing 6.2: The interface of aResponsElementStatesHandler

6.2 Runtime Environment and Transformation Structure

6.2.3 Responses

A response defines a single transformation. It implements the trigger part of a response and delegates the execution to its implicit repair routine. A concrete response is realized as an implementation of theResponseinterface, which is shown in Listing 6.3.

interface Response {

TransformationResult applyResponse(EChange change,

CorrespondenceModel<Correspondence> correspondenceModel);

boolean checkPrecondition(EChange change);

}

Listing 6.3: The interface of aResponse

The response interface does only provide two methods, which a concrete response has to implement. ThecheckPreconditionmethod realizes the trigger of a response and identifies if the response is responsible for the given change. Its implementation first checks the change type. After a positive check, the change is casted to the correct type and its properties are validated. Finally, further preconditions are checked. They are defined in a precondition block in the response language, which is realized through a dedicated method in the response implementation. TheapplyResponsemethod can be called if the checkPreconditionmethod validates the satisfaction of all preconditions. It instantiates the appropriate implicit repair routine and calls itsapplyRoutinemethod.

Based on this interface, we provide anAbstractResponseimplementation. It realizes the initialization of theResponseExecutionStatein theapplyResponsemethod and delegates the execution to anexecuteResponsemethod, which a concrete response has to implement.

6.2.4 Response Executors

AResponseExecutordefines the connector between a single transformation and the access by the transformation environment through aChange2CommandTransforming. It is sup-posed to provide appropriate access to a set of responses. In our case, such an executor is generated for each responses document, while aChange2CommandTransformingcombines all executors for a pair of metamodels. This structure eases the separation of responses for one metamodel pair into different documents and even allows the usage of responses that are generated from specifications in the mapping language because only one executor per responses source must be integrated instead of all single responses.

TheResponseExecutorinterface, which concrete executors have to implement, provides only one method, as shown in Listing 6.4. ThegenerateCommandsForEventmethod accepts a change and the correspondence model. Based on the change, a concrete executor checks

interface ResponseExecutor {

List<Command> generateCommandsForEvent(EChange change, CorrespondenceModel<Correspondence> correspondenceModel);

}

Listing 6.4: The interface of aResponseExecutor

the triggers of all the responses managed by it and creates commands that execute the responses with matching triggers.

Because all concrete executors only differ in the responses that they manage, we ad-ditionally provide anAbstractResponseExecutor, which implements the management of responses and the required execution logic. It requires the implementation of a setup method that just has to call an also providedaddResponsemethod for all the responses it is supposed to manage.

6.2.5 Repair Routines

Repair routines define the transformation logic of responses. A concrete repair routine has to implement theRepairRoutine interface, shown in Listing 6.5. It defines only an applyRoutinemethod that executes the transformation. Concrete routines expect access to certain model elements and the correspondence model, which we provide to them in the particular constructor.

public interface RepairRoutine { public void applyRoutine();

}

Listing 6.5: The interface of aRepairRoutine

Additionally to the generic interface, we provide anAbstractRepairRoutinerealization, which implements further recurring functionality. First, this abstract realization im-plements theResponseElementStatesHandlerinterface, which was introduced in subsec-tion 6.2.2, and thus provides certain methods for modifying model elements. It expects aResponseExecutionStatein the constructor to have access to the correspondence model and the user interaction implementation.

The abstract implementation also provides a method for getting a corresponding element from the correspondence model. It expects the source element, the element type, the tag and a filter method, according to the elements of the element retrieval construct in the response language. Furthermore, it implements theapplyRoutinemethod with error handling that avoids exceptions during runtime and delegates the execution to anexecuteRoutinemethod.

A concrete repair routine extending theAbstractRepairRoutinemust only implement theexecuteRoutine method. The response language constructs are realized in code by calling the appropriateResponseElementStatesHandlermethods and providing a method that implements the execution block. This execution block method is called after pre- and before post-processing the element states in theexecuteRoutinemethod.

6.2.6 Repair Routine Facades

The last artifact of the response runtime environment are repair routine facades. During the introduction of the runtime environment structure in subsection 6.2.1, we already stated that such a facade provides one method for each explicit repair routine. Just like the response executors, we provide one of these facades per source of responses respectively repair routines.

6.3 Response Language Specification and Code Generation