Java Code Generation by the TU Dresden OCL Compiler a short example constraint • I ll take the following constraint as an example context Customer inv card

Document Sample
Java Code Generation by the TU Dresden OCL Compiler a short example constraint • I ll take the following constraint as an example context Customer inv card Powered By Docstoc
					Java Code Generation by the
TU Dresden OCL Compiler

       a short example
                        constraint
• I'll take the following constraint as an example:
  context Customer inv:
  cards->forAll(printedName=self.name)
• before being converted to Java, it has to normalized:
  context Customer inv tuddOclInv0 :
  self.cards -> forAll (
     tuddOclIter0 : CustomerCard |
     tuddOclIter0.printedName=self.name
  )
• (if you press the buttons "Normalize" and then "To Text"
  on the AST tab, you'll get the normalized constraint into
  the input text area)
                      OCL library

• To understand the generated code, we'll first have a quick
  look at the OCL library. This is a Java class library that
  represents the predefined OCL types.
                       OCL library
The classes within blue borders are direct equivalents
of predefined types.
               OCL library




OclAnyImpl objects encapsulate application objects.
                    OCL library

• The classes have methods where the corresponding OCL
  types define properties.
• For example, OclBoolean has methods
   – and(OclBoolean param)
   – or(OclBoolean param)
   – implies(OclBoolean param)
• There is also a method isTrue(), which return the
  boolean value represented by the OclBoolean object.
  We'll need that later.
                  Generated Code

• Now, we generate code for our example OCL expression:
                               Generated Code
final OclAnyImpl tuddOclNode0=Ocl.toOclAnyImpl( Ocl.getFor(this) );
final OclSet tuddOclNode1=Ocl.toOclSet(tuddOclNode0.getFeature("cards"));
final OclIterator tuddOclIter0=tuddOclNode1.getIterator();
final OclBooleanEvaluatable tuddOclEval0=new OclBooleanEvaluatable() {
   public OclBoolean evaluate() {
     final OclString tuddOclNode2=
       Ocl.toOclString(Ocl.toOclAnyImpl(tuddOclIter0.getValue()).getFeature("printedName"));
     final OclString tuddOclNode3=Ocl.toOclString(tuddOclNode0.getFeature("name"));
     final OclBoolean tuddOclNode4=tuddOclNode2.isEqualTo(tuddOclNode3);
     return tuddOclNode4;
   }
};
final OclBoolean tuddOclNode5=tuddOclNode1.forAll(tuddOclIter0, tuddOclEval0);




tuddOclNode0 holds the library representation of "self"
(library representations are created by the operation Ocl.getFor(),
while the operation Ocl.toOclAnyImpl() asserts that the result is of
type OclAnyImpl or returns an appropriate undefined value otherwise)
                               Generated Code
final OclAnyImpl tuddOclNode0=Ocl.toOclAnyImpl( Ocl.getFor(this) );
final OclSet tuddOclNode1=Ocl.toOclSet(tuddOclNode0.getFeature("cards"));
final OclIterator tuddOclIter0=tuddOclNode1.getIterator();
final OclBooleanEvaluatable tuddOclEval0=new OclBooleanEvaluatable() {
   public OclBoolean evaluate() {
     final OclString tuddOclNode2=
       Ocl.toOclString(Ocl.toOclAnyImpl(tuddOclIter0.getValue()).getFeature("printedName"));
     final OclString tuddOclNode3=Ocl.toOclString(tuddOclNode0.getFeature("name"));
     final OclBoolean tuddOclNode4=tuddOclNode2.isEqualTo(tuddOclNode3);
     return tuddOclNode4;
   }
};
final OclBoolean tuddOclNode5=tuddOclNode1.forAll(tuddOclIter0, tuddOclEval0);



tuddOclNode0 now holds some Customer object. The next step is to
   get the customers Set of Cards. This is a feature defined by an
application type, and such features are accessed through the operation
   getFeature(String name). Like toOclAnyImp before, toOclSet()
                   assures that the result is an OclSet.
                               Generated Code
final OclAnyImpl tuddOclNode0=Ocl.toOclAnyImpl( Ocl.getFor(this) );
final OclSet tuddOclNode1=Ocl.toOclSet(tuddOclNode0.getFeature("cards"));
final OclIterator tuddOclIter0=tuddOclNode1.getIterator();
final OclBooleanEvaluatable tuddOclEval0=new OclBooleanEvaluatable() {
   public OclBoolean evaluate() {
     final OclString tuddOclNode2=
       Ocl.toOclString(Ocl.toOclAnyImpl(tuddOclIter0.getValue()).getFeature("printedName"));
     final OclString tuddOclNode3=Ocl.toOclString(tuddOclNode0.getFeature("name"));
     final OclBoolean tuddOclNode4=tuddOclNode2.isEqualTo(tuddOclNode3);
     return tuddOclNode4;
   }
};
final OclBoolean tuddOclNode5=tuddOclNode1.forAll(tuddOclIter0, tuddOclEval0);




 Now, things get a bit more difficult. We want to find out if a
property holds for all cards in the Set tuddOclNode1. Therefore
             we need an Iterator through the Set.
                                Generated Code
 final OclAnyImpl tuddOclNode0=Ocl.toOclAnyImpl( Ocl.getFor(this) );
 final OclSet tuddOclNode1=Ocl.toOclSet(tuddOclNode0.getFeature("cards"));
 final OclIterator tuddOclIter0=tuddOclNode1.getIterator();
 final OclBooleanEvaluatable tuddOclEval0=new OclBooleanEvaluatable() {
    public OclBoolean evaluate() {
      final OclString tuddOclNode2=
        Ocl.toOclString(Ocl.toOclAnyImpl(tuddOclIter0.getValue()).getFeature("printedName"));
      final OclString tuddOclNode3=Ocl.toOclString(tuddOclNode0.getFeature("name"));
      final OclBoolean tuddOclNode4=tuddOclNode2.isEqualTo(tuddOclNode3);
      return tuddOclNode4;
    }
 };
 final OclBoolean tuddOclNode5=tuddOclNode1.forAll(tuddOclIter0, tuddOclEval0);



In the OCL constraint, the expression "printedName=self.name"
    is the argument of the forAll property. This expression is
  transformed to an anonymous inner class that implements an
  interface "OclBooleanEvalutable", which defines nothing but
one operation "evaluate". The OCL subexpression is transformed
                 into the body of this operation.
                               Generated Code
final OclAnyImpl tuddOclNode0=Ocl.toOclAnyImpl( Ocl.getFor(this) );
final OclSet tuddOclNode1=Ocl.toOclSet(tuddOclNode0.getFeature("cards"));
final OclIterator tuddOclIter0=tuddOclNode1.getIterator();
final OclBooleanEvaluatable tuddOclEval0=new OclBooleanEvaluatable() {
   public OclBoolean evaluate() {
     final OclString tuddOclNode2=
       Ocl.toOclString(Ocl.toOclAnyImpl(tuddOclIter0.getValue()).getFeature("printedName"));
     final OclString tuddOclNode3=Ocl.toOclString(tuddOclNode0.getFeature("name"));
     final OclBoolean tuddOclNode4=tuddOclNode2.isEqualTo(tuddOclNode3);
     return tuddOclNode4;
   }
};
final OclBoolean tuddOclNode5=tuddOclNode1.forAll(tuddOclIter0, tuddOclEval0);




      The hole code within this box means nothing but
 "take the iterator's value", which is a CustomerCard object.
 Then, we take the CustomerCards printedName and store it
               in tuddOclNode2 (an OclString).
                               Generated Code
final OclAnyImpl tuddOclNode0=Ocl.toOclAnyImpl( Ocl.getFor(this) );
final OclSet tuddOclNode1=Ocl.toOclSet(tuddOclNode0.getFeature("cards"));
final OclIterator tuddOclIter0=tuddOclNode1.getIterator();
final OclBooleanEvaluatable tuddOclEval0=new OclBooleanEvaluatable() {
   public OclBoolean evaluate() {
     final OclString tuddOclNode2=
       Ocl.toOclString(Ocl.toOclAnyImpl(tuddOclIter0.getValue()).getFeature("printedName"));
     final OclString tuddOclNode3=Ocl.toOclString(tuddOclNode0.getFeature("name"));
     final OclBoolean tuddOclNode4=tuddOclNode2.isEqualTo(tuddOclNode3);
     return tuddOclNode4;
   }
};
final OclBoolean tuddOclNode5=tuddOclNode1.forAll(tuddOclIter0, tuddOclEval0);


       In the next line, we determine the value of "self.name".
      Up in the very first line we stored the value for "self" in
     tuddOclNode0. Now, we compute tuddOclNode0's feature
                "name", and store it as tuddOclNode3.
                (BTW: Here, we refer to a variable from the outer class
               from within an inner class. That's only legal in Java if the
            variable is declared "final". Hence, all the "final" declarations.)
                               Generated Code
final OclAnyImpl tuddOclNode0=Ocl.toOclAnyImpl( Ocl.getFor(this) );
final OclSet tuddOclNode1=Ocl.toOclSet(tuddOclNode0.getFeature("cards"));
final OclIterator tuddOclIter0=tuddOclNode1.getIterator();
final OclBooleanEvaluatable tuddOclEval0=new OclBooleanEvaluatable() {
   public OclBoolean evaluate() {
     final OclString tuddOclNode2=
       Ocl.toOclString(Ocl.toOclAnyImpl(tuddOclIter0.getValue()).getFeature("printedName"));
     final OclString tuddOclNode3=Ocl.toOclString(tuddOclNode0.getFeature("name"));
     final OclBoolean tuddOclNode4=tuddOclNode2.isEqualTo(tuddOclNode3);
     return tuddOclNode4;
   }
};
final OclBoolean tuddOclNode5=tuddOclNode1.forAll(tuddOclIter0, tuddOclEval0);




          The next lines are easy: We just find out if
         tuddOclNode2 (="printedName") is equal to
                tuddOclNode3 (="self.name").
       The result is then returned as the result of the hole
           subexpression "printedName=self.name".
                               Generated Code
final OclAnyImpl tuddOclNode0=Ocl.toOclAnyImpl( Ocl.getFor(this) );
final OclSet tuddOclNode1=Ocl.toOclSet(tuddOclNode0.getFeature("cards"));
final OclIterator tuddOclIter0=tuddOclNode1.getIterator();
final OclBooleanEvaluatable tuddOclEval0=new OclBooleanEvaluatable() {
   public OclBoolean evaluate() {
     final OclString tuddOclNode2=
       Ocl.toOclString(Ocl.toOclAnyImpl(tuddOclIter0.getValue()).getFeature("printedName"));
     final OclString tuddOclNode3=Ocl.toOclString(tuddOclNode0.getFeature("name"));
     final OclBoolean tuddOclNode4=tuddOclNode2.isEqualTo(tuddOclNode3);
     return tuddOclNode4;
   }
};
final OclBoolean tuddOclNode5=tuddOclNode1.forAll(tuddOclIter0, tuddOclEval0);




Now we have defined what every element in tuddOclNode1
 (the Set of CustomerCards) must fulfill, so we can call the
operation "forAll", which needs references to the iterator and
the argument expression (represented by the tuddOclEval0).
                                Generated Code
public boolean assert() {

final OclAnyImpl tuddOclNode0=Ocl.toOclAnyImpl( Ocl.getFor(this) );
final OclSet tuddOclNode1=Ocl.toOclSet(tuddOclNode0.getFeature("cards"));
final OclIterator tuddOclIter0=tuddOclNode1.getIterator();
final OclBooleanEvaluatable tuddOclEval0=new OclBooleanEvaluatable() {
   public OclBoolean evaluate() {
     final OclString tuddOclNode2=
       Ocl.toOclString(Ocl.toOclAnyImpl(tuddOclIter0.getValue()).getFeature("printedName"));
     final OclString tuddOclNode3=Ocl.toOclString(tuddOclNode0.getFeature("name"));
     final OclBoolean tuddOclNode4=tuddOclNode2.isEqualTo(tuddOclNode3);
     return tuddOclNode4;
   }
};
final OclBoolean tuddOclNode5=tuddOclNode1.forAll(tuddOclIter0, tuddOclEval0);

return tuddOclNode5.isTrue();
}

  Now tuddOclNode5 holds the value "true" iff the constraint is
   fulfilled. We can insert this code into the assert method of
                     Customer as done above
         (this should be done by a tool, but isn't so far...).
              The Royals & Loyals GUI

• Having modified (and recompiled) the file Customer.java,
  let's now try if it works. To do so, we start the Royals &
  Loyals GUI:
  java tudresden.ocl.RLObject testpop
• The argument "testpop" says that the file "testpop" will be
  used to load and store the object population. Of course,
  loading will fail since that file does not exists so far - just
  ignore the "FileNotFoundException". If you restart the
  GUI with the same command, your object population will
  be restored.
            The Royals & Loyals GUI




• By pressing one of the buttons on the top, objects are
  added to the population. Here, one customer has been
  added.
• By selecting the customer and entering a command in the
  text field (then pressing ENTER or clicking "EXECUTE"),
  simple modifications can be made to the objects
            The Royals & Loyals GUI




• References between objects can be set using "@" and the
  object's ID.
            The Royals & Loyals GUI




• Now we add card @1 to customer @0's cards.
  Note the ":Object".
             The Royals & Loyals GUI




• Now we start evaluation of the assertions be pressing the
  ASSERT button. The result is written to the console, and
  should look like this:
     --- starting assertAll ---
     testing tudresden.ocl.test.royloy.Customer 0
     - FAILED -
     testing tudresden.ocl.test.royloy.CustomerCard 1
     passed
     finished assertAll
             The Royals & Loyals GUI




• After the modification shown above, the test should not
  fail any more:
          --- starting assertAll ---
          testing tudresden.ocl.test.royloy.Customer 0
          passed
          testing tudresden.ocl.test.royloy.CustomerCard 1
          passed
          finished assertAll