<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta />
    <article-meta>
      <title-group>
        <article-title>The SDMLib solution to the Model Execution Case for TTC2015</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Stefan Lindel</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <contrib contrib-type="author">
          <string-name>Albert Zu¨ ndorf</string-name>
          <email>zuendorf@cs.uni-kassel.de</email>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>Kassel University, Software Engineering Research Group</institution>
          ,
          <addr-line>Wilhelmsho ̈her Allee 73, 34121 Kassel</addr-line>
          ,
          <country country="DE">Germany</country>
        </aff>
      </contrib-group>
      <pub-date>
        <year>2014</year>
      </pub-date>
      <abstract>
        <p>This paper describes the SDMLib solution to the Model Execution case for the TTC2015 [1]. We solved all case variants and did all performance tests. For this case we generated the Java implementation of the activity diagram classes with SDMLib in order to have an efficient model representation. Then we modeled the operations using SDMLib model transformations. These model transformations were embedded into methods of the activity diagram classes leveraging the overriding of methods for the distinction of different behavior for different kinds of activity nodes. Our solution deviates from the case description in the handling of tokens: instead of consuming and recreating tokens we use just one token and allow it to be at several places at a time and we just move the token forward through the activity diagram. This results in more elegant modeling and faster execution.</p>
      </abstract>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>Introduction</title>
      <sec id="sec-1-1">
        <title>NamedElement</title>
        <p>name : String
currentE
lem
ents *
token 1</p>
      </sec>
      <sec id="sec-1-2">
        <title>Activity</title>
        <p>activity 1
token 1</p>
        <p>Token
1 * 1 *
noOfVisitors : int nodes * activity 1
ecru gni tegr gni
os ogt at moc</p>
        <p>uo ni</p>
      </sec>
      <sec id="sec-1-3">
        <title>ActivityNode</title>
        <p>activity 1</p>
      </sec>
      <sec id="sec-1-4">
        <title>ActivityEdge</title>
        <p>edges *
will remove itself from the currentElements and add its target object (e.g. o11 instead. In addition, the
noOfVisitors attribute of the target object is incremented. Later on, when the JoinNode j7 is executed,
j7 checks its noOfVisitors. If this is lower than the number of incoming ControlFlows, not all parallel
executions have reached the JoinNode yet and thus, the JoinNode deletes the currentElements link
but does not forward it. Only when noOfVisitors indicates that all parallel branches have reached the
JoinNode, the currentElements link is forwarded to the outgoing ControlFlow.</p>
      </sec>
    </sec>
    <sec id="sec-2">
      <title>2 The model execution transformations</title>
      <p>The initialization of the model execution, the handling of variables and expressions, and the overall run loop
are described in the 5. To give an idea of SDMLib model transformations we discuss a generalized version
of method ActivityNode.run().</p>
      <p>The overall execution identifies the current Activity node or ControlFlow edge and calls the run method
of the active object. Thereby new elements become active and this is iterated until the final node is reached.
Method run() of class NamedElement is overridden within its subclasses to achieve specific behavior for
the various activity diagram elements. Listing 1 and Figure 3 show the general behavior of activity nodes.
// add to trace
TracePO t r a c e P O = a c t i v i t y N o d e P O . h a s A c t i v i t y ( ) . h a s T r a c e ( ) ;
t r a c e P O . c r e a t e E x e c u t e d N o d e s ( a c t i v i t y N o d e P O ) ;
target
nodes
executedNodes.1 trace t15 : Trace</p>
      <p>a1 : Activity
activitytracename=ytivitcatest2 actaaivccitttyiivviittyy
&gt;&gt; s.2
crete edNde
a o
&lt;&lt; cut
e
x
e
r
g
a
t
nodes a9 : ActivityFinalNode
running=true
name= nalNode2
noOfVisitors=0</p>
      <p>cni te
edges gnimo
c8 : ControlFlow
name=edge8
guardValue=false
outgoing
t
e
g
tr
a
g
n
i
m
o
c
n
i
c6 : ControlFlow
outgoing name=edge6</p>
      <p>guardValue=false
o11 : OpaqueAction
target running=true
noOfVisitors=0
name=action3
o5 : OpaqueAction
running=true
target noOfVisitors=0
name=action2
source
edges
c10 : ControlFlow
source
&lt;&lt;crceuartree&gt;nt&gt;Elements</p>
      <p>incoming
11
12
13
14
15
16
17
18
19</p>
      <p>Generally, the model transformation executing an ActivityNode starts with an activityNodePO Pattern
Object bound to the model object this, cf. line 3 of Listing 1. Then, line 6 uses a chain of has operations
to look-up the owning Activity and the attached tracePO. Line 7 adds the current ActivityNode to the
Trace. Then, we look up the tokenPO that is attached to the current ActivityNode (line 10) and remove
the corresponding currentElements link (line 11). Now we forward the token. Thus, line 14 looks for
a2 : ActivityPO
activity
f1 : ActivityNodePO
&lt;&lt;create&gt;&gt;
executedNodes
currentElem&lt;en&lt;tsdetsotkroeyn&gt;&gt;
t4 : TokenPO</p>
      <p>&lt;&lt;crceuarrteen&gt;tE&gt;lements
outgoing activityEdgePO matches and line 16 adds such ActivityEdge objects to the current Token.
As there may be multiple outgoing ActivityEdge objects, line 18 asks the current Pattern to apply on all
matches. Thus all outgoing ActivityEdges are added to the currentElements.</p>
      <p>Note, the activity diagrams used as test cases provided by case description have no usual activity nodes
that have more than one outgoing control flow. Only, fork nodes and decision nodes have multiple outgoing
edges. For fork nodes, the general behavior works fine. For decision nodes, we override the run() method
and extend the general execution pattern by a check for the guard of the outgoing ActivityEdge. Only if
the guard is true, the corresponding activity edge is added to the currentElements. For decision nodes, it
is guaranteed, that only one outgoing control flow has a guard that evaluates to true. Thus, we do not need an
allMatches for decision nodes. For JoinNodes we just extend the general ActivityNode.run() pattern
with a check whether the noOfVisitors equals the number of incomming ControlFlows. Only then the
Token is forwarded.</p>
      <p>The SDMLib implementation of the Model Execution Case provided in the SHARE environment has
dedicated run methods for each kind of activity diagram element. Only when writing this paper we
recognized that a common run method in class ActivityNode would have covered most cases, elegantly. After
writing the paper we just had no time to update the SHARE version.</p>
    </sec>
    <sec id="sec-3">
      <title>3 Results</title>
      <p>Once we decided to come up with our own concept for moving tokens, it was pretty straight forward to
develop the corresponding model transformations. The simplified token concept also resulted in model
transformations that do very little search through to-many associations. The model transformations mainly
look-up the current situation and and check all kinds of conditions on it. Thus, we think the execution is
reasonably fast. The following table shows our performance measurements executed on a laptop with a 64
Bit Intel Dual Core i7 CPU M620 2.67GHz with 8 GB memory.</p>
      <p>performance test
execution time (milli seconds)
variant 1
9.99 ms
variant 2
9.25 ms
variant 3.1 variant 3.2
9.38 ms 14.05 ms
4</p>
    </sec>
    <sec id="sec-4">
      <title>Summary</title>
      <p>For the performance measurement we did the usual tricks like warming up the Java virtual machine
hot compiler by executing each activity 1000 times before measurement. We than ran each test 5 times
and computed the average runtime. Overall, we think the performance test cases are a little bit to small
to measure the model transformation execution time without side effects and overheads from other things
running in the virtual machine.
Overall, the model execution case fits very well to SDMLib. It was quite straight forward to model the
different execution steps and the different steps have a complexity that justifies the usage of model transformation
in comparison to hand written Java code.</p>
      <p>To some extend both the performance of our solution and the simplicity of the deployed model
transformations benefit from our simplified token handling concept. However, sticking with the predefined token
handling in most cases just means that the corresponding model transformations need one more statement to
delete the old token and one more statement to create a new token. Thus the complexity of the model
transformations would grow only slightly. The measurement of the resulting performance would be interesting.</p>
      <p>The class model provided with the case uses a lot of inheritance and enumeration types. Actually,
SDMLib can still be improved in dealing with inheritance. This is current work. Enumerations are used
e.g. for the operators in expression trees. We evaluate such expression trees with usual Java code. Model
transformation seem not to give leverage here.</p>
    </sec>
    <sec id="sec-5">
      <title>Appendix</title>
      <p>As a start, Listing 2 shows the Java source code that builds and runs the SDMLib model transformation
initializing the variables of an activity. Figure 4 shows this transformation graphically1.
1
2
3
4
5
6
7
8</p>
      <p>}
c l a s s A c t i v i t y {
p u b l i c v o i d i n i t V a r i a b l e s ( ) {</p>
      <p>A c t i v i t y P O a c t i v i t y P O = new A c t i v i t y P O ( t h i s ) ;
V a r i a b l e P O l o c a l V a r i a b l e P O = a c t i v i t y P O . h a s L o c a l s ( ) ;
ValuePO v a l u e P O = l o c a l V a r i a b l e P O . h a s I n i t i a l V a l u e ( ) ;
l o c a l V a r i a b l e P O . c r e a t e C u r r e n t V a l u e ( v a l u e P O ) ;
l o c a l V a r i a b l e P O . d o A l l M a t c h e s ( ) ;</p>
      <p>Listing 2: Initialize variables transformation in Java</p>
      <p>In SDMLib a model transformation is called a Pattern and it consists of Pattern Objects and Pattern
Links that are matched against actual model objects. For the initialization of activity variables we use a
1SDMLib is able to render a model transformation as HTML or SVG.
Pattern with three Pattern Objects: activityPO, localVariablePO, and valuePO. The constructor call
new ActivityPO(this) creates the Pattern and adds the activityPO Pattern Object to it and binds
activityPO to the current model object this. This means, the Pattern Object activityPO is directly
matched against the model object this. It will also serve as start for the pattern matching process.</p>
      <p>Next, the command activityPO.hasLocals() creates the Pattern Object localVariablePO and a
Pattern Link of type locals that connects activityPO and localVariablePO. Then, the pattern matching
is initiated and SDMLib tries to find model objects of type Variable that are connected to the current
Activity object via a locals link. If there are multiple candidates, the candidates are stored for as possible
matches. One of the candidates is chosen as the current match. If there is no match for a given Pattern
Object, backtracking is initiated and SDMLib tries to chose other candidates for previously visited Pattern
Objects and then revisits the current Pattern Object. If backtracking fails, too, the whole matching fails.
In the current example case let us assume that there are two variables v1 and v2. Thus Pattern Object
localVariablePO will be matched e.g. against v1 and v2 will be stored as alternative candidate.</p>
      <p>SDMLib generates the Method hasLocals() within class ActivityPO from the association locals
between the classes Activity and Variable. For each association role such a has method is generated
in the corresponding PO class. These has methods create a Pattern Link according to the role name and a
Pattern Object according to the role’s target class.</p>
      <p>Line 5 of Listing 2 extends the search Pattern by an valuePO Pattern Object connected to localVariablePO
via an initialValue link. Next, line 6 uses method createCurrentValue to extend our model
transformation by an action that creates a currentValue link between the model objects matched by localVariablePO
and valuePO. This create action is executed only if the Pattern has a successful match.</p>
      <p>Finally, line 7 calls method doAllMatches. Method doAllMatches triggers the backtracking of the
Pattern search, i.e. we go back to choices where still alternatives are available. In our example, this is the
matching of localVariablePO to var1. Thus, localVariablePO is now re-matched against v2 and the
remaining pattern matching, i.e. the search for a value and the creation of a currentValue link is executed
again. Method doAllMatches triggers backtracking until the Pattern search and execution fails. Overall,
now all local variables of the current activity are initialized.</p>
      <p>Model transformation initVariables is the first operation called within method run() of class Activity,
cf. Listing 3. Similarly, method input() uses an doAllMatches transformation to assign input values to
variables. Lines 5 and 6 each look-up the set of all ActivitNode model objects within the current
activity. To implement to-many associations SDMLib generates special set classes for all model classes as
in this case class ActivityNodeSet. These set classes inherit from a general container class and in
addition for each method of the model class SDMLib generates a similar method in the corresponding set
class. For example the method withRunning(boolean) of class ActivityNode() results in a similar
method in class ActivityNodeSet. In the set class, the generated method iterates through all contained
elements and forwards the method call to each of them. Thus, line 5 of Listing 3 is finally calling method
withRunning(boolean) on each ActivityNode in the current Activity. This sets the state of all
activity nodes to running. Similarly, line 6 sets the noOfVisitors attribute of all activity nodes to 0;
// run the token
Token t o k e n = tokenPO . g e t C u r r e n t M a t c h ( ) ;
w h i l e ( ! t o k e n . g e t C u r r e n t E l e m e n t s ( ) . i s E m p t y ( ) )</p>
      <p>NamedElement f i r s t = t o k e n . g e t C u r r e n t E l e m e n t s ( ) . f i r s t ( ) ;
f i r s t . r u n ( ) ;</p>
      <p>Listing 3: Method Activity.run() in Java</p>
      <p>Lines 8 to 14 of Listing 3 build and run the central model transformation employed in method Activity.run().
This model transformation is shown graphically in Figure 5. Again, the Pattern starts with an activityPO
Pattern Object bound to the current Activity model object, cf. line 8. This is extended by a nodes link to
an activityNodePO, cf. line 9. This time we especially look for an activty node of type InitialNode. In
the current version of SDMLib we have to use a special instanceOf() method to model this type check
in our Pattern. This results in another Pattern Object of the desired type in line 10. In the graphical
visualization this is rendered by an instanceOf link to another Pattern Object of the desired type. However,
these two Pattern Object will match against the same model object. As this is somewhat intricate, we plan to
enhance SDMLib to generate specific hasNodesOfTypeInitalNode methods that include the type check,
internally.</p>
      <p>Once we have identified the initial node, we create a Trace object (line 12) and a Token object (line 13).
Finally, the method call createCurrentElements(initialNodePO) creates a currentElements link
between the model objects matched by tokenPO and initialNodePO (line 14).
nodes</p>
      <p>a2 : ActivityNodePO
&lt;&lt; create&gt;
token
&gt;
t5 : TokenPO
&lt;&lt; create&gt;&gt;
instanceOf i3 : InitialNodePO
&lt;&lt;cucrrreenatteE&gt;le&gt;ments</p>
      <p>
        Generally, the described model transformation searches through all nodes of the given activity in order
to find the node of type InitialNode. This has a runtime complexity of O(n) in the number of activity
nodes. However, in the example cases, the initial node is always the first node in the list of activity nodes.
Thus, the pattern search always succeeds on the first activity node it visits and thus the actual runtime is
O(
        <xref ref-type="bibr" rid="ref1">1</xref>
        ).
      </p>
      <p>Once the Trace and the Token object are created, the actual execution of the activity diagram is driven
by lines 17 through 23 of Listing 3. First, we look up the model object token that correspond to the
Pattern Object tokenPO (line 17). The loop of line 19 uses the currentElements link of our token
object as a queue, it looks-up the first element and calls run() on it. The run method will remove the
corresponding currentElements link and add new (successor) elements to the currentElements instead.
Note, currentElements may point to ActivityNode objects as well as to ActivityEdge objects. Thus,
loop variable first uses the common super type NamedElement.</p>
      <p>Listing 4 and Figure 6 show the execution of ControlFlow objects. Line 4 starts with a controlFlowPO
Pattern Object bound to the current ControlFlow model object. Line 5 adds the current tokenPO. In any
case, we destroy the currentElements link to the Token as the ControlFlow is now executed. Now we
want to ensure that the guard of the ControlFlow allows the execution. Actually, this is not necessary as
the decision node does not add a ControlFlow to the currentElements unless its guard is true. However,
for completeness, ControlFlow.run() checks this condition, too. Unfortunately, there are two different
cases to consider: first the ControlFlow may have no guard at all. Then it shall be consider to be true. And
second, if the ControlFlow has a guard, than the value of that guard has to be true. To cover both cases at
once, we ensure that the ControlFlow has no guard with value false. This may fail if there is no guard or
if the guard is true. If it fails, we move the token forward. In our model transformation we use a negative
application condition NAC, cf. line 11 through 18. The sub pattern within the NAC tries to find a match.
If that succeeds, the NAC fails and the overall pattern is not executed, any more. Line 13 and 14 look-up a
Guard at the controlFlowPO and test that this Guard is an instance of a BooleanVariable and that this
BooleanVariable has a currentValue. Line 16 then ensures that the currentValue is instance of a
BooleanValue and that the BooleanValue has the value false.
1 p u b l i c c l a s s C o n t r o l F l o w e x t e n d s A c t i v i t y E d g e {
2 @Override
p u b l i c v o i d r u n ( ) {</p>
      <p>ControlFlowPO c o n t r o l F l o w P O = new ControlFlowPO ( t h i s ) ;
TokenPO tokenPO = c o n t r o l F l o w P O . hasToken ( ) ;
// in any case remove from currentElements
tokenPO . d e s t r o y C u r r e n t E l e m e n t s ( c o n t r o l F l o w P O ) ;
// add successor if guard allows
c o n t r o l F l o w P O . s t a r t N A C ( ) ;</p>
      <p>If there is no guard preventing it, line 21 of Listing 4 identifies the target of our ControlFlow and
line 23 adds this target to the currentElements. Finally, line 26 uses a lambda expression to add an
currentEle&lt;m&lt;ednetssttrookye&gt;n&gt;
t2 : TokenPO
target
a7 : ActivityNodePO
noOfVisitors++
&lt;&lt;ccurreraetnet&gt;El&gt;ements
operation to our model transformation that on execution increments the noOfVisitors of the target.</p>
      <p>OpaqueAction nodes may have a number of expressions attached to them. Expression objects
provide their own run() methods executing them. Thus, for OpaqueAction nodes we override the ActivityNode
run() method to call the Expression.run() method on each expression. The expressions use various
subclasses and various enumeration types to distinguish between different operations. Thus, each subclass
provides its specific run() method and these specific run() methods use traditional switch statements to
deal with the corresponding enumeration types, cf. Listing 5. Alternatively, we might have provided Model
Patterns for each case, however evaluating expression trees is not really the application domain for model
patterns.</p>
      <p>I n t e g e r V a l u e v a l 1 = ( I n t e g e r V a l u e ) t h i s . g e t O p e r a n d 1 ( ) . g e t C u r r e n t V a l u e ( ) ;
I n t e g e r V a l u e v a l 2 = ( I n t e g e r V a l u e ) t h i s . g e t O p e r a n d 2 ( ) . g e t C u r r e n t V a l u e ( ) ;
i n t op1 = v a l 1 . g e t V a l u e ( ) ;
i n t op2 = v a l 2 . g e t V a l u e ( ) ;
d e f a u l t :</p>
      <p>throw new U n s u p p o r t e d O p e r a t i o n E x c e p t i o n ( ""+ t h i s . g e t O p e r a t o r ( ) ) ;
t h i s . g e t A s s i g n e e ( ) . s e t C u r r e n t V a l u e ( new I n t e g e r V a l u e ( ) . w i t h V a l u e ( r e s u l t ) ) ;</p>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          <article-title>[1] TTC2015 The Model Execution Case</article-title>
          . https://code.google.com/a/eclipselabs.org/p/moliz/source/browse/?repo=ttc2015,
          <year>2015</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          [2]
          <string-name>
            <given-names>Story</given-names>
            <surname>Driven Modeling Library</surname>
          </string-name>
          . http://sdmlib.org/,
          <year>2014</year>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>