| <html> |
| |
| <head> |
| <meta HTTP-EQUIV="Content-Type" |
| CONTENT="text/html; charset=windows-1252"> |
| <title>How to process OCL Abstract Syntax Trees</title> |
| <link rel="stylesheet" href="../article.css"> |
| </head> |
| |
| <body> |
| <h1 ALIGN="CENTER">How to process OCL Abstract Syntax Trees</h1> |
| |
| <div class="summary"> |
| <h2>Summary</h2> |
| |
| <p>The MDT OCL project provides the building blocks for Model-Driven |
| tools to weave OCL declarative specifications into software artifacts. |
| We showcase some of these possibilities, taking as starting point a |
| plug-in to visualize OCL ASTs in the form of annotated trees. This |
| example motivates some practical tips about patterns for OCL visitors, |
| including using Java 5 generics and achieving conciseness by letting MDT |
| OCL take care of the "walking" order. To really reap the |
| benefits of OCL-enriched specifications, tools in our modeling chain |
| have to be able to transform such expressions into the target software |
| platform (e.g. compile into Java, translate into SQL). Work in this area |
| is summarized, to ease jump-starting your own OCL processing project.</p> |
| |
| <div class="author">By <a |
| href="http://www.sts.tu-harburg.de/~mi.garcia/">Miguel Garcia</a>, |
| Technische Universität Hamburg-Harburg (Germany)</div> |
| <div class="copyright">Copyright © 2007 Miguel Garcia. Made |
| available under the EPL v1.0</div> |
| <div class="date">April 30th, 2007</div> |
| </div> |
| |
| <div class="content"> |
| <h2>The building blocks at our disposal</h2> |
| |
| <p>The MDT OCL framework supports all the way from parsing a textual |
| OCL expression to evaluating such expression on some object population, |
| for both Ecore and UML2 models. This requires some infrastructure, which |
| MDT OCL provides as visitors for:</p> |
| <ul> |
| <li>validating the concrete-syntax tree (CST) prepared by the |
| parser (such tree contains instances of <tt>OCLCST.ecore</tt>)</li> |
| <li>resolving identifiers to declarations, i.e. transforming a CST |
| into an AST, whose nodes are instances of classes defined in <tt>OCL.ecore</tt>. |
| |
| |
| </li> |
| <li>evaluating an OCL AST, with <tt>org.eclipse.ocl.internal.evaluation.EvaluationVisitorImpl</tt> |
| being in charge of this</li> |
| </ul> |
| <p></p> |
| |
| The functionality listed above is accessed through a façade, <tt>org.eclipse.ocl.OCL</tt>. |
| Details will be given later, but a quote from <a |
| href="http://wiki.eclipse.org/index.php/MDT_1.0_New_and_Noteworthy"><i>MDT |
| New and Noteworthy</i></a> is useful at this point: |
| |
| <blockquote>The new <tt>org.eclipse.ocl.OCL</tt> generic |
| class is the focal point of OCL parsing and evaluation. Besides creating |
| <tt>org.eclipse.ocl.helper.OCLHelper</tt>s for parsing embedded |
| constraints and <tt>org.eclipse.ocl.Query</tt>s for evaluating |
| constraints, it can also parse OCL documents (text files external to the |
| model).</blockquote> |
| |
| <p>Although this article does not focus on concrete-syntax trees |
| prepared by the parser, two remarks are in order. First, CST classes are |
| internal, i.e. not part of the public API of the MDT OCL plug-in. And |
| second, the validation of a CST is actually performed by the same |
| visitor in charge of the CST to AST conversion.</p> |
| |
| <p>OCL expressions cannot be understood in isolation, they always |
| appear in the context of some model element. Sample contexts include:</p> |
| <ul> |
| <li>a class (all OCL invariants have a class as context)</li> |
| <li>a class property (for example, an OCL query to compute a |
| derived attribute has that attribute as context)</li> |
| <li>an operation (pre- and postconditions, <tt>body</tt> |
| expressions)</li> |
| </ul> |
| The context of an expression determines which model elements are visible |
| in the expression. For example, the formal arguments to an operation can |
| be referred in a precondition but not in a class invariant. |
| <p></p> |
| |
| The article <a |
| href="http://www.eclipse.org/articles/Article-EMF-Codegen-with-OCL/article.html"><i>Implementing |
| Model Integrity in EMF with MDT OCL</i></a> describes the JET templates that |
| take as input a user-written EMF model with OCL annotations and generate |
| Java method bodies that evaluate these expressions at runtime. So, what |
| else could be left to do? Actually, a lot. For example: |
| <ul> |
| <li>we've carefully written OCL invariants to specify which object |
| populations should be ruled out according to the requirements (e.g. car |
| drivers younger than 16, a PC configuration with an under-rated power |
| supply). After code generation we may happily perform CRUD (Create, |
| Retrieve, Update, Delete) <i>yet the responsibility rests on the |
| developer to check whether invariants have been broken</i>. An efficient |
| mechanism to collect information in the background as updates are |
| performed would serve the purpose of flawlessly detecting invalid |
| snapshots of object populations.</li> |
| <li>again we've carefully written OCL queries, that we can invoke |
| as long as all objects reside in-memory. While ORM (Object-Relational |
| Mapping) engines contain optimizations to minimize the performance |
| impact of retrieving objects from a persistent store, the best of both |
| worlds could be achieved with the automatic translation of OCL into SQL |
| or into EJB3's query language.</li> |
| </ul> |
| |
| Links about these areas and a summary of work in progress can be found |
| at the end of this article. For now, we'll focus on the more humble goal |
| of depicting OCL ASTs (much like <a |
| href="http://www.eclipse.org/jdt/ui/astview/index.php">ASTView</a> |
| depicts the AST of the Java compilation unit that's being edited). For |
| example: |
| |
| <p></p> |
| <p></p> |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img src="images/myPNG/tree01.PNG" alt="OCL AST 01"></td> |
| </tr> |
| <caption align="bottom"><b>Figure 1</b> Visual depiction of |
| the AST for the invariant <br /> |
| <tt>self.participants->forAll(c1, c2 | c1 <> c2 implies c1.name <> |
| c2.name)</tt></caption> |
| </table> |
| <p></p> |
| <p>It could be argued that, if OCL is human-readable, why is an AST |
| view needed at all? The answer is that it comes handy not just for those |
| writing OCL-processing algorithms, but for everyone. Consider the |
| following unparenthesized invariant:</p> |
| <pre> |
| currentLevel.name = 'Silver' implies card.color = Color::silver and currentLevel.name = 'Gold' implies card.color = Color::gold |
| </pre> How is it to be interpreted? |
| |
| <p></p> |
| <p></p> |
| <table border="1" cellpadding="8"> |
| <tr> |
| <th>Like this ...</th> |
| <th>... or like this?</th> |
| </tr> |
| <tr> |
| <td><pre> |
| (currentLevel.name = 'Silver' |
| implies |
| card.color = Color::silver) |
| and |
| (currentLevel.name = 'Gold' |
| implies |
| card.color = Color::gold) |
| </pre></td> |
| <td><pre> |
| ( currentLevel.name = 'Silver' |
| implies |
| (card.color = Color::silver and currentLevel.name = 'Gold') |
| ) |
| implies |
| ( self.card.color = Color::gold ) |
| </pre></td> |
| </tr> |
| </table> |
| <p></p> |
| <p></p> |
| <h3>Software configuration for this article</h3> |
| |
| <p>This article assumes some familiarity with OCL syntax. The |
| examples shown are part of a case study (Royal & Loyal) originally |
| discussed in the book <i>"The Object Constraint Language. |
| Getting your models ready for MDA"</i> by Warmer and Kleppe, as well as |
| in the following course notes:</p> |
| <ul> |
| <li><a |
| href="http://www.cse.dmu.ac.uk/~aoc/teaching-notes/Contents/CSCI3007/OCL.htm">CSCI3007 |
| OCL Tutorial</a><br /> |
| </li> |
| <li><a |
| href="http://www.cse.dmu.ac.uk/~aoc/teaching-notes/Contents/CSCI3007/CSCI3007OCLtutorial.pdf">CSCI3007 |
| accompanying case study</a><br /> |
| </li> |
| </ul> |
| <p></p> |
| |
| <p>Following the tradition of other OCL tools, the Royal & Loyal |
| case study is followed (its class diagram can be found in Appendix A). |
| Both <a href="./files/RandL.ecore">EMF</a> and <a |
| href="./files/RandL.uml">UML2</a> versions are provided . The R&L model |
| contains samples for all OCL language constructs. We'll discuss some of |
| them in connection with our viewer. This model can be explored with any |
| editor that allows selecting model elements (e.g. the built-in Sample |
| Ecore Model Editor, or some graphical editor). The contained OCL |
| expressions can thus be modified and new ones added. You won't get |
| feedback on syntax checks with those editors (as the OCL annotations are |
| opaque to them). For that, installing the <a href="./install/plugins/OCLASTView_1.0.0.jar">OCLASTView |
| plug-in</a> is needed.</p> |
| |
| <blockquote> |
| <p><img src="images/tip.gif" width="62" height="13" alt=""> In |
| order to have an <tt>.uml</tt> file initialized with the contents of a |
| pre-existing <tt>.ecore</tt> file, you may do one of the following: (a) |
| right click on the corresponding Ecore <tt>.genmodel</tt>, select |
| "Export Model..." and then "UML model". |
| Alternatively, you can (b) open the Ecore model, select the <tt>EPackage</tt> |
| you want to convert, and then from the "Sample Ecore Editor" |
| menu (in the main menu bar) choose "Convert to UML Model ...". |
| You will need the <tt>org.eclipse.uml2.examples</tt> plug-ins to see |
| those menu options.</p> |
| </blockquote> |
| |
| <p>The interactive evaluation of OCL expressions against a |
| particular object population is not the focus of this article. For that, |
| the <a |
| href="http://help.eclipse.org/help32/index.jsp?topic=/org.eclipse.emf.ocl.doc/references/examples/oclInterpreterExample.html">OCL |
| Interpreter</a> delivered as part of <a |
| href="http://www.eclipse.org/modeling/mdt/downloads/?project=ocl">MDT |
| OCL</a> can be used. It accepts ad-hoc OCL expressions provided by the user |
| at runtime, also allowing serializing them to <tt>.xmi</tt>. This |
| document can be explored with the standard XMI editor provided by EMF, |
| however OCLASTView has been designed to display OCL ASTs in a more |
| readable format. A comparison can be found in Appendix B.</p> |
| |
| <h2>Visitors are our friends</h2> |
| <p>The occurrences of OCL language constructs are internally |
| represented in ASTs as instances of the OCL "metamodel" |
| classes (depicted in Figure 2). In the AST shown in Figure 1, the root |
| is an <tt>IteratorExp</tt>. This particular iterator (a <tt>forAll</tt> |
| with two iterator variables) evaluates whether the boolean condition |
| expressed in its body is <tt>true</tt> for all pairs of items in the |
| source collection (the source collection being <tt>self.participants</tt>, |
| whose type is <tt>OrderedSet(Customer)</tt>). As a whole, this <tt>forAll</tt> |
| reports whether items with duplicate names exist. OCLASTView depicts |
| iterators with the source collection as first child, the iterator |
| variables as second child, and the boolean expression as third child |
| (just like the appearance order in the textual syntax). More diagrams of |
| the OCL 2.0 metamodel can be found in the latest spec by the OMG, <a |
| href="http://www.omg.org/cgi-bin/doc?formal/2006-05-01">formal/2006-05-01</a>. |
| </p> |
| |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img src="images/myPNG/OCLMM.png" |
| alt="Fragment of the OCL 2.0 metamodel (only inheritance relationships shown)"></td> |
| </tr> |
| <caption align="bottom"><b>Figure 2</b> Fragment of the OCL |
| 2.0 metamodel (only inheritance relationships shown)</caption> |
| </table> |
| <p>MDT OCL contains great examples of visitors for OCL processing, |
| e.g. to obtain the textual representation of an OCL AST (<tt>ToStringVisitor</tt>). |
| These visitors can be easily spotted in that they implement interface <tt>org.eclipse.ocl.utilities.Visitor</tt>. |
| </p> |
| |
| <blockquote> |
| <p><img src="images/tip.gif" width="62" height="13" alt=""> A |
| useful starting point for writing your own visitor is the abstract class |
| <tt>AbstractVisitor</tt> which shows how to visit children nodes for |
| each OCL construct.</p> |
| </blockquote> |
| |
| <p>Let's say we've got a reference <tt>myExp</tt> to an <tt>OCLExpression</tt> |
| (the root interface of the OCL metamodel) most probably obtained as a |
| result of invoking <tt>OCLHelper#createQuery(String expression)</tt>. |
| The <tt>OCLExpression</tt> interface extends <tt>Visitable</tt>, |
| therefore we can invoke <tt>myExp.accept(myVisitor)</tt> on it. Assuming |
| that <tt>myExp</tt> is the AST for the <tt>forAll</tt> expression in |
| Figure 1, and thanks to overriding, the <tt>accept()</tt> method in <tt>IteratorExpImpl</tt> |
| will be invoked, which in turn delegates to a handler for that language |
| construct in our visitor. Before getting to see the <img |
| src="images/tag_1.gif" height="13" width="24" align="CENTER" alt=""> |
| default implementation of <tt>AbstractVisitor#visitIteratorExp()</tt>, |
| please notice that:</p> |
| <ul> |
| <li>the usage of generic types in that method will be explained |
| shortly</li> |
| <li>an OCL iterator expression (e.g. <tt>forAll</tt>) evaluates |
| its body for each item in the source collection. Such body refers to a |
| variable, a variable which takes as value (in each evaluation) one of |
| the items in the source collection. Incidentally, <tt>forAll</tt> is |
| special in that it's the only OCL iterator expression allowing more |
| than one variable, so as to allow Cartesian products. If you really |
| want to know more about what an AST node for the <tt>forAll</tt> |
| construct looks like, you may jump ahead to Figure 3, where its |
| metamodel class is depicted.</li> |
| </ul> |
| |
| <p>Coming back to the source code, first for <img |
| src="images/tag_1.gif" height="13" width="24" align="CENTER" alt=""> |
| the default implementation of <tt>AbstractVisitor#visitIteratorExp()</tt> |
| and then for <img src="images/tag_2.gif" height="13" width="24" |
| align="CENTER" alt=""> its specialization in <tt>ToStringVisitor</tt> |
| (which overrides it to generate the textual syntax for the iterate |
| expression, the opposite process to parsing):</p> |
| <pre><img src="images/tag_1.gif" height="13" width="24" |
| align="CENTER" alt=""> public T visitIteratorExp(IteratorExp<C, PM> callExp) { |
| T sourceResult = callExp.getSource().accept(this); |
| |
| List<T> variableResults; |
| List<Variable<C, PM>> variables = callExp.getIterator(); |
| |
| if (variables.isEmpty()) { |
| variableResults = Collections.emptyList(); |
| } else { |
| variableResults = new java.util.ArrayList<t>(variables.size()); |
| for (Variable<C, PM> iterVar : variables) { |
| variableResults.add(iterVar.accept(this)); |
| } |
| } |
| |
| T bodyResult = callExp.getBody().accept(this); |
| |
| return handleIteratorExp(callExp, sourceResult, variableResults, bodyResult); |
| } |
| |
| protected T handleIteratorExp(IteratorExp<C, PM> callExp, |
| T sourceResult, List<T> variableResults, T bodyResult) { |
| return null; |
| } |
| |
| </pre> |
| |
| <p>The above implementation performs no processing at all, it just |
| visits all nodes. Instead, the <img src="images/tag_2.gif" height="13" |
| width="24" align="CENTER" alt=""> override in <tt>ToStringVisitor</tt> |
| returns a string of the form</p> |
| <tt><i>sourceCollection</i>-><i>iteratorName</i>(<i> |
| iteratorVariables</i> | <i>iteratorBody </i>)</tt> <br /> |
| <pre> |
| <img src="images/tag_2.gif" height="13" width="24" align="CENTER" alt=""> protected String handleIteratorExp(IteratorExp<C,PM> callExp, |
| String sourceResult, List<String> variableResults, String bodyResult) { |
| |
| StringBuffer result = new StringBuffer(); |
| |
| String name = callExp.getName(); |
| result.append(sourceResult).append("->").append(name).append('('); //$NON-NLS-1$ |
| |
| for (Iterator<String> iter = variableResults.iterator(); iter.hasNext();) { |
| result.append(iter.next()); |
| if (iter.hasNext()) { |
| result.append(", ");//$NON-NLS-1$ |
| } |
| } |
| |
| result.append(" | ").append(bodyResult).append(')');//$NON-NLS-1$ |
| |
| return result.toString(); |
| } |
| |
| </pre> |
| |
| <p><tt>ToStringVisitor</tt> needs only override <tt>handleIteratorExp()</tt> |
| to get its job done, as <tt>visitIteratorExp()</tt> takes up the |
| recurrent duty of visiting the owned parts, moreover passing such |
| results (<tt>String</tt>s in this case) as actual arguments to <tt>handleIteratorExp()</tt>. |
| In case the default visit order established by <tt>AbstractVisitorImpl</tt> |
| is not deemed appropriate for some particular scenario, its <tt>visit...</tt> |
| methods can be overridden. This is necessary for example when evaluating |
| an OCL <tt>if-then-else-endif</tt>: the else part is be evaluated only |
| in case the condition part evaluates to false. This is precisely what <tt>EvaluationVisitorImpl#visitIfExp()</tt> |
| does.</p> |
| |
| <h2>Generics are our friends, too</h2> |
| |
| <p>It's a fact of life that MDT OCL makes copius use of Generics. |
| However it's a small set of type parameters that's used over and over |
| again. With a bit of practice you'll recognize in a flash that <tt>C</tt> |
| stands for either an EMF <tt>org.eclipse.emf.ecore.EClassifier</tt> or |
| an UML2 <tt>org.eclipse.uml2.uml.Classifier</tt>. The complete list of |
| type parameters is described in the Javadoc for the interface <tt>org.eclipse.ocl.Environment</tt> |
| (reproduced below for ease of reference while reading this article). In |
| fact, there is a method to all this, and the Type Hierarchy helps in |
| visualizing it. <tt>Environment</tt> has two subtypes: <tt>EcoreEnvironment</tt> |
| and <tt>UMLEnvironment</tt>, where the correct type substitutions appear |
| for easy reference. Other types exhibiting the same pattern include <tt>org.eclipse.ocl.OCL</tt>, |
| <tt>org.eclipse.ocl.utilities.UMLReflection</tt>, and <tt>org.eclipse.ocl.utilities.ExpressionInOCL</tt>. |
| </p> |
| |
| <p>The intriguing <tt>T</tt> type parameter in the code above stands |
| for the result type of visitor methods. For example, the declaration of |
| <tt>ToStringVisitor</tt> subclasses <tt>AbstractVisitor</tt> by |
| substituting the generic <tt>T</tt> return type with <tt>String</tt>. In |
| detail,</p> |
| |
| <pre>public class ToStringVisitor<C, O, P, EL, PM, S, COA, SSA, CT> |
| extends AbstractVisitor<String, C, O, P, EL, PM, S, COA, SSA, CT> |
| </pre> |
| |
| <p>Given that some types have specializations providing type |
| substitutions for Ecore and for UML2, a natural question is why <tt>AbstractVisitor</tt> |
| does not follow the same pattern. After all, one could type:</p> |
| |
| <pre>public class AbstractVisitorEcore<T> |
| extends AbstractVisitor<T, EClassifier, EOperation, EStructuralFeature, |
| EEnumLiteral, EParameter, EObject, |
| CallOperationAction, SendSignalAction, org.eclipse.ocl.ecore.Constraint> </pre> |
| |
| <p>(by checking what substitutions are used in <tt>EcoreEnvironment</tt>) |
| and then let the Java Development Tools perform auto-completion given |
| the start of a method name, for example:</p> |
| |
| <pre> |
| @Override |
| protected T handleIteratorExp(IteratorExp<EClassifier, EParameter> callExp, |
| T sourceResult, List<T> variableResults, T bodyResult) { |
| // TODO Auto-generated method stub |
| return super.handleIteratorExp(callExp, sourceResult, variableResults, |
| bodyResult); |
| } |
| </pre> |
| |
| <p>This move is not as smart as it might seem at first sight given |
| that the very benefits of Generics are lost: any OCL visitor extending <tt>AbstractVisitorEcore</tt> |
| will only work on Ecore-based models, although it could have most |
| probably worked on UML2-based models as well. Bounded generics allow |
| writing algorithms which minimally depend on the types of the input, |
| while preserving static type-safety. That's the reason why <tt>EvaluationVisitorImpl</tt>, |
| for example, has no specializations: its methods work for models |
| expressed in either of Ecore or UML2.</p> |
| |
| <table border="1"> |
| <tr> |
| <td> |
| |
| <h3><font SIZE="1"> org.eclipse.ocl</font> <br> |
| Interface Environment<PK,C,O,P,EL,PM,S,COA,SSA,CT,CLS,E></h3> |
| <dl> |
| <dt></dt> |
| <dt><b>Type Parameters:</b></dt> |
| <dd><code>PK</code> - is substituted by the metaclass |
| representing the metamodel's analogue for the UML 2.x <tt>Package</tt> |
| </dd> |
| <dd><code>C</code> - corresponds to the UML <tt>Classifier</tt> |
| metaclass</dd> |
| <dd><code>O</code> - corresponds to the UML <tt>Operation</tt> |
| metaclass</dd> |
| <dd><code>P</code> - corresponds to the UML <tt>Property</tt> |
| metaclass</dd> |
| <dd><code>EL</code> - corresponds to the UML <tt>EnumerationLiteral</tt> |
| metaclass (<tt>Enumeration</tt>s are simply represented as |
| classifiers)</dd> |
| <dd><code>PM</code> - corresponds to the UML <tt>Parameter</tt> |
| metaclass</dd> |
| <dd><code>S</code> - corresponds to the UML <tt>State</tt> |
| metaclass (for metamodels that describe state machines)</dd> |
| <dd><code>COA</code> - corresponds to the UML <tt>CallOperationAction</tt> |
| metaclass (used in message expressions)</dd> |
| <dd><code>SSA</code> - corresponds to the UML <tt>SendSignalAction</tt> |
| metaclass (used in message expressions)</dd> |
| <dd><code>CT</code> - corresponds to the UML <tt>Constraint</tt> |
| metaclass</dd> |
| <dd><code>CLS</code> - corresponds to the UML <tt>Class</tt> |
| metaclass</dd> |
| <dd><code>E</code> - corresponds to the UML <tt>Element</tt> |
| metaclass</dd> |
| </dl> |
| <dl> |
| <dt><b>All Known Implementing Classes:</b></dt> |
| <dd>AbstractEnvironment, EcoreEnvironment, UMLEnvironment</dd> |
| </dl> |
| |
| </td> |
| </tr> |
| </table> |
| |
| |
| <p>With this brief exposition to the OCL metamodel and the usage of |
| parametric polymorphism in MDT OCL, we set out to build our first OCL |
| visitor.</p> |
| |
| <h2>First visitor: a visualizer of OCL ASTs</h2> |
| |
| <p>A tree-based visualization of OCL expressions helps big time in |
| familiarizing with the structure of the different kinds of nodes in OCL |
| ASTs, and thus we will get that visitor to work first (a slightly more |
| sophisticate visitor, a simplifier of arithmetic expressions, comes |
| next).</p> |
| |
| <p>We cover first the visitor itself (devoid of UI aspects), leaving |
| for the next section the plug-in extension that defines the view to |
| display the tree prepared by the visitor. This view mostly consists of |
| code generated by a PDE wizard. The remaining bits and pieces (how to |
| track the current selection in an Ecore editor, how to parse OCL, how to |
| display an XML document in a TreeViewer) are described in detail |
| elsewhere.</p> |
| |
| <h3>What to do in the handler for a leaf node</h3> |
| |
| <p>It makes sense to consider first what output we want for leaf |
| nodes in OCL ASTs. These nodes are recognized because <tt>AbstractVisitor</tt> |
| defines their handler to simply <tt>return null;</tt> no owned nodes are |
| visited, and thus no <tt>handler...</tt> method is defined for such |
| construct. In our case, we want our visitor to prepare an XML element to |
| show the node kind and type. Some leaf nodes have additionally a value, |
| e.g. all the <tt>...LiteralExp</tt> ones: they stand for literal |
| constants of some type. We will also display such literal constants as |
| attributes of an XML node. In summary, leaf nodes are handled by:</p> |
| <pre> |
| public T visitVariableExp(VariableExp<C, PM> v); |
| public T visitTypeExp(TypeExp<C> t); |
| public T visitUnspecifiedValueExp(UnspecifiedValueExp<C> unspecExp); |
| public T visitStateExp(StateExp<C, S> stateExp); |
| public T visitIntegerLiteralExp(IntegerLiteralExp<C> literalExp); |
| public T visitRealLiteralExp(RealLiteralExp<C> literalExp); |
| public T visitStringLiteralExp(StringLiteralExp<C> literalExp); |
| public T visitBooleanLiteralExp(BooleanLiteralExp<C> literalExp); |
| public T visitNullLiteralExp(NullLiteralExp<C> literalExp); |
| public T visitInvalidLiteralExp(InvalidLiteralExp<C> literalExp); |
| public T visitEnumLiteralExp(EnumLiteralExp<C, EL> literalExp); |
| public T visitUnlimitedNaturalLiteralExp(UnlimitedNaturalLiteralExp<c> literalExp) |
| |
| </pre> |
| |
| <p>These are the methods we'll implement first in class <a |
| href="./files/oclastview/XMLforOCL.java.html"><tt>XMLforOCL</tt></a> |
| which extends <tt>AbstractVisitor</tt> and that imports classes from the |
| MDT OCL plug-in (the plug-ins that OCLASTView depends on are shown in |
| Figure 11 below)</p> |
| |
| <p>Method <img src="images/tag_3.gif" height="13" width="24" |
| align="CENTER" alt=""> <tt>visitVariableExp()</tt> in <tt>XMLforOCL</tt> |
| handles usages of variables in OCL. <tt>VariableExp</tt> references the |
| declaration of the referred variable, i.e. it references a <tt>org.eclipse.ocl.expressions.Variable<C, |
| PM></tt>:</p> |
| <pre> |
| @Override |
| <img src="images/tag_3.gif" height="13" width="24" align="CENTER" alt=""> public Element visitVariableExp(VariableExp<C, PM> v) { |
| Variable<C, PM> vd = v.getReferredVariable(); |
| Element res = new Element("VariableExp"); //$NON-NLS-1$ |
| res.setAttribute("name", vd.getName()); //$NON-NLS-1$ |
| addTypeInfo(res, v); |
| return res; |
| } |
| |
| private void addTypeInfo(org.jdom.Element res, TypedElement<C> exp) { |
| C ec = exp.getType(); |
| String tName = getName(ec); |
| res.setAttribute("type", tName); //$NON-NLS-1$ |
| } |
| |
| |
| </pre> An OCL expression may contain literals for primitive datatypes (Real, |
| Integer, Boolean, String). A handler for such occurrences of literals in |
| an AST node typically looks like: <pre> |
| @Override |
| public Element visitRealLiteralExp(RealLiteralExp<C> literalExp) { |
| Element res = new Element("RealLiteralExp"); //$NON-NLS-1$ |
| res.setAttribute("symbol", Double.toString(literalExp.getRealSymbol())); //$NON-NLS-1$ |
| return res; |
| } |
| |
| </pre> Two novelties of OCL 2.0 are the built-in literal values <tt>null</tt> |
| and <tt>OclInvalid</tt> which may appear in the textual syntax. In |
| general, an expression any of whose arguments is <tt>OclInvalid</tt> |
| evaluates to <tt>OclInvalid</tt>, that value propagates during |
| evaluation much like <tt>NULL</tt> does in SQL. By including an |
| invocation to <tt>addTypeInfo()</tt> our handlers will reveal what the |
| types of those literal values are (and they better have one, as OCL is a |
| strongly-typed language). The instances returned are maintained by MDT |
| OCL, they are part of the <i>symbol tables</i> (in |
| compiler-implementation terminology) and form part of the bookkeeping |
| required to parse, validate against <i>static semantics</i>, and |
| transform OCL expressions. |
| |
| <h3>What to do in the handlers for non-leaf nodes</h3> |
| |
| <p>According to our definition, non-leaf nodes are those whose |
| metamodel class defines one or more containment associations, as for |
| example <tt>IfExp</tt>, <tt>IterateExp</tt>, and <tt>IteratorExp</tt>:</p> |
| |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img src="images/myPNG/IfExp.PNG" |
| alt=" Containment associations for IfExp and LoopExp "></td> |
| </tr> |
| <caption align="bottom"><b>Figure 3</b> Containment |
| associations for <tt>IfExp</tt> and <tt>LoopExp</tt></caption> |
| </table> |
| |
| <p>The <tt>XMLforOCL</tt> handler of <tt>IfExp</tt> simply pieces |
| together the results of visiting the owned parts (just like <tt>ToStringVisitor</tt> |
| does). These results (<tt>conditionResult</tt>, <tt>thenResult</tt>, and |
| <tt>elseResult</tt>) are never null because according to the |
| well-formedness rules of OCL an <tt>IfExp</tt> must have those three |
| parts and visitors are coded under the assumption of well-formed input. |
| Notice also that had not been <tt>org.jdom.Element</tt> substituted for |
| the type parameter <tt>T</tt>, the visitor would have resorted to |
| explicit type-casts (downcasts from <tt>Object</tt> to <tt>Element</tt>). |
| Generics instead enable compile-time type-checking.</p> |
| <pre> |
| @Override |
| protected org.jdom.Element handleIfExp(IfExp<c> ifExp, Element conditionResult, |
| Element thenResult, Element elseResult) { |
| Element res = new Element("IfExp"); //$NON-NLS-1$ |
| Element eConditionPart = new Element("condition"); //$NON-NLS-1$ |
| eConditionPart.addContent(conditionResult); |
| res.addContent(eConditionPart); |
| |
| Element eThenPart = new Element("then"); //$NON-NLS-1$ |
| eThenPart.addContent(thenResult); |
| res.addContent(eThenPart); |
| |
| Element eElsePart = new Element("else"); //$NON-NLS-1$ |
| eElsePart.addContent(elseResult); |
| res.addContent(eElsePart); |
| return res; |
| } |
| </pre> |
| |
| <h3>What sets <tt>CallExp</tt> and its subtypes apart from the rest</h3> |
| |
| <p>We've written handlers returning <tt>org.jdom.Element</tt> for |
| several OCL constructs by considering them in isolation, without |
| worrying about other sub-expressions in the whole OCL expression. This |
| we can make for <tt>IfExp</tt>, the <tt>...LiteralExp</tt>, and in |
| general for metamodel classes which are not subtypes of <tt>CallExp</tt>, |
| as a <tt>CallExp</tt> further evaluates some <i>source expression</i> |
| which can be obtained with <tt>getSource()</tt>. For example, the |
| metamodel in Figure 2 shows that a <tt>PropertyCallExp</tt> is a subtype |
| of <tt>CallExp</tt>. That explains why we can write: <tt>self.age |
| >= 18</tt>, where <tt>age</tt> stands for an attribute. (The <tt>VariableExp</tt> |
| <tt>self</tt> is its source expression). What EMF calls <tt>EStructuralFeature</tt> |
| (an attribute or a reference) OCL calls <i>property</i>, also in |
| agreement with UML terminology.</p> |
| |
| <p>In terms of OCL visitors this means that for each instance of <tt>CallExp</tt> |
| its source expression should be visited, and the <tt>visit...</tt> |
| methods in <tt>AbstractVisitor</tt> do just that. This behavior was |
| already shown in <img src="images/tag_1.gif" height="13" width="24" |
| align="CENTER" alt=""> and <img src="images/tag_2.gif" |
| height="13" width="24" align="CENTER" alt="">, the default AST |
| visitor and the serializer into textual representation, respectively. |
| The root node in Figure 1 has <tt><source></tt> as a subnode only |
| because in our overridden <tt>handleIteratorExp</tt> the following was |
| done:</p> |
| <pre> |
| Element sourceE = new Element("source"); |
| sourceE.addContent(sourceResult); |
| res.addContent(sourceE); |
| </pre> |
| |
| <p>Other OCL constructs owning sub-expressions occur in connection |
| with the initializers of variables and the arguments of operation calls. |
| As a sidenote, in programming-language parlance, OCL's |
| "source" is usually called "target", while in OCL <tt>MessageExp</tt>s |
| the target is actually named "target".</p> |
| |
| <h3>Things we swept under the carpet</h3> |
| |
| <p>We've overriden so far the methods highlighted in Figure 4. The |
| remaining ones follow the same principles and can be found in the |
| finished <a href="./files/oclastview/XMLforOCL.java.html"><tt>XMLforOCL</tt></a>. |
| </p> |
| |
| <p>Exploring the list of not-yet-implemented methods reveals a type |
| that cannot be found in the fragment of the OCL metamodel depicted in |
| Figure 2 (<tt>TupleLiteralPart</tt>). Implementing another method (<tt>visitCollectionLiteralExp()</tt>) |
| reveals a containment association to types also not shown in Figure 2 (<tt>CollectionItem</tt> |
| and <tt>CollectionRange</tt>, taken together the only subtypes of <tt>CollectionLiteralPart</tt>, |
| also not shown in Figure 2). Finally, we've implemented a handler (<tt>visitVariable()</tt>) |
| for a type nowhere to be found in Figure 2. What's going on? As Figure 5 |
| shows, not all OCL constructs have counterparts subtyping <tt>OCLExpression</tt> |
| in the metamodel (Figure 2 depicts only the classes branching off from <tt>OCLExpression</tt>). |
| </p> |
| |
| <table border="0" cellpadding="8"> |
| <tr valign="bottom"> |
| <td><img src="images/myPNG/overriddenSoFar.PNG" alt="Methods |
| making up our><tt>XMLforOCL</tt> visitor so far "> |
| <p /><b>Figure 4</b> Public methods overridden in <tt>XMLforOCL</tt> |
| so far |
| </td> |
| <td><img src="images/myPNG/wholeStoryAboutTheOCLMM.PNG" |
| alt=" aa "> |
| <p /><b>Figure 5</b> The whole story about the OCL metamodel: <br /> |
| not all OCL language constructs subtype <tt>OCLExpression</tt> |
| </td> |
| </tr> |
| </table> |
| <p>To complete the picture on visiting <tt>Variable</tt>s, version |
| 1.1 of MDT OCL introduces the <tt>ExpressionInOcl</tt> metaclass |
| (described in Chapter 12 of the <a |
| href="http://www.omg.org/cgi-bin/doc?formal/2006-05-01">OCL spec</a>). |
| This metaclass does not subtype <tt>TypedElement</tt> but <tt>Visitable</tt> |
| and constitutes the container for context variables (<tt>self</tt>, <tt>result</tt>) |
| and for those variables standing for operation parameters (if any). As |
| for other OCL constructs, <tt>AbstractVisitor#visitExpressionInOCL()</tt> |
| will visit those owned parts, passings the results to <tt>AbstractVisitor#handleExpressionInOCL()</tt>. |
| </p> |
| |
| |
| <h3>Variables and environments: how they show up in OCL ASTs</h3> |
| |
| <p>Navigation in OCL expressions as enabled by <tt>CallExp</tt> is |
| very useful. Some constructs however must serve as anchors, i.e. they |
| have no source expression themselves. We've met some of them already: |
| all the <tt>...LiteralExp</tt> ones, <tt>VariableExp</tt>, <tt>IfExp</tt>, |
| and <tt>LetExp</tt>. The remaining constructs without a source share the |
| property of being subtypes of <tt>OCLExpression</tt> but not of <tt>CallExp</tt>: |
| <tt>TypeExp</tt>, <tt>UnspecifiedValueExp</tt>, <tt>StateExp</tt>, and <tt>MessageExp</tt>. |
| </p> |
| |
| <p>There's a distinction between <tt>VariableExp</tt> and <tt>Variable</tt>, |
| the former denotes a usage and the latter a declaration. The declaration |
| for a usage is accessible through <tt>VariableExp#getReferredVariable()</tt>. |
| The AST builder in MDT OCL makes available as pre-defined some variables |
| in some OCL expression contexts:</p> |
| <ul> |
| <li><tt>self</tt> in classifier and operation contexts</li> |
| <li>a variable for each formal argument in an operation context</li> |
| <li><tt>result</tt> in the postcondition context of an operation. |
| </li> |
| <li>Additionally, <tt>@pre</tt> may postfix in the postcondition |
| context a property, to indicate the value it had before execution of |
| the operation. More in detail, the <tt>FeatureCallExp</tt> metaclass |
| defines the <tt>isMarkedPre</tt> property. Unfortunately, Section 8.3.2 |
| "FeatureCall Expressions" of the <a |
| href="http://www.omg.org/cgi-bin/doc?formal/2006-05-01">OCL spec</a> |
| omits the description of the <tt>FeatureCallExp</tt> metamodel class. |
| More importantly, a <tt>VariableExp</tt> cannot be marked with <tt>@pre</tt> |
| because variables (such as operation parameters or <tt>Let</tt> |
| variables) don't exist before the invocation of the operation (thanks |
| to Christian W. Damus for these observations).</li> |
| </ul> |
| <p>The constructs <tt>let</tt>, all the iterators (<tt>IteratorExp</tt>) |
| and <tt>iterate</tt> (<tt>IterateExp</tt>) allow defining (sometimes |
| implicit) variables. For example, Figure 1 shows the <tt>forAll</tt> |
| iterator defining two explicit variables (<tt>c1</tt>, <tt>c2</tt>). |
| Implicit iterator variables instead are nowhere to be seen in the |
| textual syntax, thus contributing to its conciseness, but are revealed |
| by the AST builder anyway. For example, Figure 6 depicts the invariant</p> |
| <p><tt>participants->forAll(age() <= 70)</tt></p> |
| <p>where both <tt>self</tt> and the iterator variable over the <tt>participants</tt> |
| collection are implicit. In the AST tree view the explicit declaration |
| of the iterator variable (<tt>temp20</tt>) is shown in red, and its |
| usage in green (Figure 6).</p> |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img src="images/myPNG/implicitIteratorVar.PNG" |
| alt="Implicit iterator variable "></td> |
| </tr> |
| <caption align="bottom"><b>Figure 6</b> Implicit iterator |
| variable (<tt>temp20</tt>)</caption> |
| </table> |
| <p>Moreover, the OCL syntax allows for a <tt>collect</tt> iterator |
| to be elided from the textual syntax, to support the intuitive concept |
| of "dot navigation". This feature can be seen at work in |
| Figure 7.</p> |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img src="images/myPNG/elidedCollect.PNG" |
| alt="Elided collect "></td> |
| </tr> |
| <caption align="bottom"><b>Figure 7</b> Elided <tt>collect</tt> |
| </caption> |
| </table> |
| |
| <p>With some more work, the OCL AST visualizer can be extended to |
| show the variables available in the current environment of a |
| sub-expression.</p> |
| |
| <p>The following section covers GUI issues, setting the ground for |
| covering later our last visitor, a simplifier of arithmetic expressions.</p> |
| |
| <h2>The UI for OCL visitors</h2> |
| |
| <p>We'll use the same UI mechanisms for all the visitors in this |
| article: a TreeViewer to display an XML document. The only differences |
| will be in the document to build and how it's built. As first step, we |
| activate the wizard File > New > Plug-in Project, and make the |
| choices shown in Figures 8 to 10.</p> |
| |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img src="images/myPNG/PDEwizard.PNG" |
| alt="Step 1 of PDE Wizard to create the OCLASTView plug-in "></td> |
| </tr> |
| <caption align="bottom"><b>Figure 8</b> Step of the PDE |
| Wizard to create the OCLASTView plug-in</caption> |
| </table> |
| |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img src="images/myPNG/PDEwizard2.PNG" |
| alt="Step of PDE Wizard to create the OCLASTView plug-in "></td> |
| </tr> |
| <caption align="bottom"><b>Figure 9</b> Step of the PDE |
| Wizard to create the OCLASTView plug-in</caption> |
| </table> |
| |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img src="images/myPNG/PDEwizard3.PNG" |
| alt="Step of PDE Wizard to create the OCLASTView plug-in "></td> |
| </tr> |
| <caption align="bottom"><b>Figure 10</b> Step of the PDE |
| Wizard to create the OCLASTView plug-in</caption> |
| </table> |
| |
| <p>In the just created plugin.xml the dependencies shown in Figure |
| 11 are added:</p> |
| |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img src="images/myPNG/oclDependency.PNG" |
| alt="Dependencies of the OCLASTView plug-in "></td> |
| </tr> |
| <caption align="bottom"><b>Figure 11</b> Dependencies of the |
| OCLASTView plug-in</caption> |
| </table> |
| |
| <h3>Making OCLASTView track the current editor selection</h3> |
| |
| <p>In its current state, the view generated by the wizard can be |
| shown alongside the Ecore or UML editor we've chosen yet it is unaware |
| about the current selection. We want it instead to display the XML tree |
| so laboriously built for an OCL-annotated operation or classifier. Some |
| classes cherry-picked from other plug-ins save the day (they've been |
| placed in the <tt>util</tt> package in the source code of <a |
| href="./install/plugins/OCLASTView_1.0.0.jar">OCLASTView</a>):</p> |
| <ul> |
| <li><tt>JDomContentProvider</tt> and <tt>JDomLabelProvider</tt>, |
| reproduced from the BSD-licensed <a |
| href="http://octopus.sourceforge.net">Octopus</a></li> |
| </ul> |
| |
| <p>Finally, we make the view implement <tt>ISelectionListener</tt> |
| with <tt>selectionChanged()</tt> checking whether a valid context has |
| been selected (an operation or a classifier, to later check whether that |
| context has a valid OCL annotation. At the XMI level, an OCL annotation |
| looks as shown in Figure 12:</p> |
| |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img src="images/myPNG/oclAtXMIlevel.PNG" |
| alt="OCL Annotation "></td> |
| </tr> |
| <caption align="bottom"><b>Figure 12</b> How an OCL |
| annotation really looks in an .ecore file</caption> |
| </table> |
| |
| <p>Using the Sample Ecore editor the same OCL invariant looks as |
| shown in Figure 13:</p> |
| |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img src="images/myPNG/oclAtECoreEditorLevel.PNG" |
| alt="OCL Annotation "></td> |
| </tr> |
| <caption align="bottom"><b>Figure 13</b> More human oriented |
| view of an OCL expression in the Ecore Sample Editor</caption> |
| </table> |
| |
| <p>Go ahead and click operations at will, the <a |
| href="./files/oclastview/OCLASTView.java.html"><tt>OCLASTView</tt></a> |
| will get notified and will update the view as a result of parsing the |
| string containing the OCL expression and visiting it (debug for |
| increased thrill)</p> |
| <pre> |
| private Element displayOCL(String expression, EObject context, String key) { |
| org.eclipse.ocl.OCL ocl = null; |
| org.eclipse.ocl.helper.OCLHelper helper = null; |
| |
| Element res = new Element(key); |
| res.setAttribute("textualInput", expression); |
| |
| if (context instanceof org.eclipse.uml2.uml.NamedElement) { |
| ocl = org.eclipse.ocl.uml.OCL.newInstance(); |
| } else { |
| ocl = org.eclipse.ocl.ecore.OCL.newInstance(); |
| } |
| |
| helper = ocl.createOCLHelper(); |
| |
| // set our helper's context object to parse against it |
| if ((context instanceof org.eclipse.emf.ecore.EClass) |
| || (context instanceof org.eclipse.uml2.uml.Classifier)) { |
| helper.setContext(context); |
| } else if (context instanceof org.eclipse.emf.ecore.EOperation) { |
| EOperation eOp = (EOperation) context; |
| helper.setOperationContext(eOp.getEContainingClass(), eOp); |
| } else if (context instanceof org.eclipse.uml2.uml.Operation) { |
| org.eclipse.uml2.uml.Operation op = (org.eclipse.uml2.uml.Operation) context; |
| helper.setOperationContext(op.getOwner(), op); |
| } else if (context instanceof org.eclipse.emf.ecore.EStructuralFeature) { |
| EStructuralFeature sf = (EStructuralFeature) context; |
| helper.setAttributeContext(sf.getEContainingClass(), sf); |
| } else if (context instanceof org.eclipse.uml2.uml.Property) { |
| org.eclipse.uml2.uml.Property p = (org.eclipse.uml2.uml.Property) context; |
| helper.setAttributeContext(p.getOwner(), p); |
| } |
| |
| OCLExpression<EClassifier> oclExp = null; |
| Element xmlAST = null; |
| try { |
| oclExp = helper.createQuery(expression); |
| } catch (Exception e) { |
| xmlAST = reportException(e); |
| res.addContent(xmlAST); |
| return res; |
| } |
| |
| XMLforOCL xfo = null; |
| if (context instanceof org.eclipse.uml2.uml.NamedElement) { |
| xfo = XMLforOCL.getUML2Version(); |
| } else { |
| xfo = XMLforOCL.getEcoreVersion(); |
| } |
| try { |
| <img src="images/tag_4.gif" height="13" width="24" align="CENTER" alt=""> xmlAST = (Element) oclExp.accept(xfo); |
| } catch (Exception e) { |
| xmlAST = reportException(e); |
| } |
| |
| res.addContent(xmlAST); |
| return res; |
| } |
| |
| </pre> |
| |
| <h3>Using OCLASTView with Ecore editors</h3> |
| |
| <p>Just to show that it's possible, the figure below depicts the |
| example Ecore editor provided by GMF triggering an update of OCLASTView:</p> |
| |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img src="images/myPNG/fromGMFEcoreEditor.PNG" |
| alt="Using OCLASTView with GMF's Ecore editor "></td> |
| </tr> |
| <caption align="bottom"><b>Figure 14</b> Using OCLASTView |
| with GMF's Ecore editor</caption> |
| </table> |
| |
| <p><a href="http://www.alphaworks.ibm.com/tech/emfatic">Emfatic</a> |
| can also be used to edit an OCL-annotated Ecore model, yet its Outline |
| view does not provide an <tt>EOperation</tt> selection. Emfatic makes |
| however for quick editing of OCL expressions themselves, as depicted in |
| Figure 15. Additionally, a new version of Emfatic is being developed. |
| For details check <a |
| href="http://www.sts.tu-harburg.de/%7Emi.garcia/SoC2007/ImprovementsToTheEmfaticEditor.pdf"> |
| this document</a>. The new features include: syntax to account for EMF |
| Generics, folding, hovers displaying the declaration of the element |
| under the cursor, hyperlinks, AutoEdits, templates, and Type Hierarchy, |
| among others.</p> |
| |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img src="images/myPNG/oclAtEmfaticLevel.PNG" |
| alt="OCL Annotation "></td> |
| </tr> |
| <caption align="bottom"><b>Figure 15</b> OCL expression in |
| Emfatic</caption> |
| </table> |
| |
| <h3>Using OCLASTView with UML editors</h3> |
| |
| <a |
| href="http://www.eclipse.org/modeling/mdt/?project=uml2tools#uml2tools">UML2 |
| Tools</a> consists of a set of GMF-based editors for viewing and editing UML |
| models. A diagram similar to that shown in Figure 16 can be obtained by |
| right-clicking on <a href="./files/RandL.uml">the UML version of |
| Royal & Loyal</a> and choosing "Initialize umlclass_diagram". |
| |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img src="images/myPNG/fromUML2ToolsEditors.PNG" |
| alt="Using OCLASTView with UML2 Tools editor "></td> |
| </tr> |
| <caption align="bottom"><b>Figure 16</b> Using OCLASTView |
| with the UML2 Tools editor</caption> |
| </table> |
| |
| <p>OCLASTView also works with the built-in UML Model Editor, as |
| shown below:</p> |
| |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img src="images/myPNG/fromUMLModelEditor.PNG" |
| alt="Using OCLASTView with the UML Model Editor "></td> |
| </tr> |
| <caption align="bottom"><b>Figure 17</b> Using OCLASTView |
| with the UML Model Editor</caption> |
| </table> |
| |
| <h2>Second visitor: simplification of arithmetic expressions |
| involving literal constants only</h2> |
| |
| <p>Whether an OCL expression is interpreted or compiled, one way to |
| make OCL evaluation faster consists in computing at <i>compile-time</i> |
| as much as possible of the expression, as a result of analyses such as <i>constant |
| folding</i> or <i>strength reduction</i> or <i>common sub-expression |
| elimination</i> or <i>partial redundancy elimination</i> |
| (compiler-implementation terminology, for an overview see <a |
| href="http://charlotte.gac.edu/+max/courses/S2005/MCS-388/pre.pdf">Max |
| Hailperin's course notes</a>) or <i>partial evaluation</i> (functional |
| programming terminology). We will tap into this area by showcasing a |
| visitor to clone an input OCL expression, except that arithmetic |
| sub-expressions involving only literal constants will be reduced to |
| their final result.</p> |
| |
| <p>This is actually the first example involving <i>processing</i>, |
| in this case transformation, of an OCL expression. So far we've just |
| relied on the AST builder to resolve identifiers to declarations and in |
| general provide us with well-formed ASTs. As we output an <i>updated</i> |
| AST thanks to an algorithm of our invention, we have to make sure that <i>we</i> |
| in turn play by the rules and return a valid AST.</p> |
| <blockquote> |
| <p><img src="images/tip.gif" width="62" height="13" alt=""> |
| You may want to review the checks for well-formedness embodied in <tt>org.eclipse.ocl.internal.parser.ValidationVisitor</tt>.</p> |
| </blockquote> |
| |
| <p>Moreover, it would be nice if we documented the set of OCL |
| expressions that our algorithm has been designed to handle (it's all |
| right to write a visitor that covers only a subset of OCL, as long as |
| that visitor reports whether it can cope with the input or not).</p> |
| |
| <p>The sketched reduction is not the only possible one, logical |
| operations can be simplified according to de Morgan rules, and so on. In |
| such visitors one wants to return unmodified AST nodes most of the time |
| . In the arithmetic reduction case, a modified AST is returned only from |
| the handler for <tt>OperationCallExp</tt> in case both the source |
| expression and the argument are any of <tt>RealLiteralExp</tt> or <tt>IntegerLiteralExp</tt>. |
| In the resulting OCL expression, the <tt>CallExp</tt> (if any) that was |
| referencing the old (unmodified) source expression should be changed to |
| point to the freshly instantiated AST node. The behavior we saw in <tt>AbstractVisitor</tt> |
| for subtypes of <tt>CallExp</tt> (visiting the source, visiting the |
| contained nodes, doing processing, return) hints at how to implement |
| this.</p> |
| |
| <p>It would be cumbersome to duplicate over and over that strategy |
| whenever a "reducer" visitor is written. Instead, we'll code <a |
| href="./files/arithmeticSimplification/OCLCloner.java.html"><tt>OCLCloner</tt></a> |
| to provide such behavior by default. A new visitor need only override |
| those methods where it may detect an opportunity for applying a |
| reduction, invoking the non-overridden version in case the preconditions |
| for the reduction are not fulfilled. For example, method <tt>visitOperationCallExp()</tt> |
| in <a |
| href="./files/arithmeticSimplification/OCLArithSimplifier.java.html"><tt>OCLArithSimplifier</tt></a> |
| starts as follows:</p> |
| <pre> |
| @Override |
| protected Visitable handleOperationCallExp( |
| OperationCallExp<C, O> callExp, Visitable sourceResult, |
| List<Visitable> argumentResults) { |
| int opcode = callExp.getOperationCode(); |
| if (!isArithmeticOp(callExp)) { |
| return super.handleOperationCallExp(callExp, sourceResult, argumentResults); |
| } |
| OCLExpression<C> newSource = (OCLExpression<C>) sourceResult; |
| OCLExpression<C> newArg = (OCLExpression<C>) argumentResults.get(0); |
| if (!(newSource instanceof NumericLiteralExp) |
| || !(newArg instanceof NumericLiteralExp)) { |
| return super.handleOperationCallExp(callExp, sourceResult, argumentResults); |
| } |
| /* |
| * actual reduction comes here |
| */ |
| |
| </pre> |
| |
| <blockquote> |
| <p><img src="images/tip.gif" width="62" height="13" alt=""> A |
| visitor is not limited to letting other components know of its |
| processing only through return values, it may also update instance |
| state. This is frequently the case with <i>chains of visitors</i>: a |
| visitor receives as argument in its constructor the previous one. |
| However, for reduction-style visitors no instance state has been |
| necessary.</p> |
| </blockquote> |
| |
| <blockquote> |
| <p><img src="images/tryit.gif" width="61" height="13" alt=""> |
| You can plug <tt>OCLArithSimplifier</tt> into <tt>OCLASTView#displayOCL()</tt> |
| to display as XML the reduced AST. Just let <tt>oclExp</tt> in <tt>OCLASTView#displayOCL()</tt> |
| accept an instace of this visitor, right before <img |
| src="images/tag_4.gif" height="13" width="24" align="CENTER" alt="">, |
| as follows:</p> |
| <pre> |
| XMLforOCL xfo = null; |
| OCLArithSimplifier simplifier = null; |
| |
| if (context instanceof org.eclipse.uml2.uml.NamedElement) { |
| xfo = XMLforOCL.getUML2Version(); |
| simplifier = OCLArithSimplifier.getUML2Version(); |
| } else { |
| xfo = XMLforOCL.getEcoreVersion(); |
| simplifier = OCLArithSimplifier.getEcoreVersion(); |
| } |
| try { |
| oclExp = (OCLExpression) oclExp.accept(simplifier); |
| <img src="images/tag_4.gif" height="13" width="24" align="CENTER" alt=""> xmlAST = (Element) oclExp.accept(xfo); // |
| } catch (Exception e) { |
| xmlAST = reportException(e); |
| } |
| </pre></blockquote> |
| |
| <h2>Conclusion</h2> |
| |
| <p>In spite of having been around for some years now, the best times |
| for OCL are yet to come by leveraging <i>model compilers</i> to map |
| declarative specifications into the chosen target software architecture. |
| Some projects and prototypes in this field are mentioned for further |
| exploration:</p> |
| |
| <ul> |
| <li>The definition of domain-specific languages goes beyond a |
| grammar specification and includes so-called well-formedness rules to |
| validate ASTs of sentences in that language. OCL has proven successful |
| as a means to specify those rules. Having language metamodels with OCL |
| enables building better tooling for such domain-specific languages. |
| Examples of <i>machine-checked</i> metamodels include <a |
| href="http://www.cs.kent.ac.uk/pubs/2004/2027/index.html">a |
| metamodel for BPEL 1.1</a> by Dave Akehurst and <a |
| href="http://www.sts.tu-harburg.de/~mi.garcia/pubs/atem06/paper/Garcia_ATEM06_Formalizing_the_well-formedness_rules_of_EJB3QL_in_UML_OCL.pdf">a |
| metamodel for EJB3QL</a> (also called JPQL) by this author.</li> |
| |
| <li>The phrase GUI generation is commonly equated to mean CRUD |
| (Create-Retrieve-Update-Delete). The problem with generators of CRUD |
| GUIs is that the only model-level information they have at their |
| disposal is the class model without OCL. OCL-aware generation of GUIs |
| instead results in warnings at runtime after performing updates that |
| break invariants, and in graying-out actions whose preconditions are |
| not fulfilled. Even without modeling behavior (in this case, user |
| tasks) in the input models, taking OCL into account in code generation |
| contributes to both the productivity and the quality of the software |
| development process.</li> |
| |
| <li>More ideas on simplification of OCL (sometimes for improved |
| readability, need not always be for performance!) can be found in <a |
| href="http://www.risc.uni-linz.ac.at/people/mgiese/pub/models05.pdf">this |
| paper</a> and in <a |
| href="http://www.risc.uni-linz.ac.at/people/mgiese/pub/ocl04sim.pdf">this |
| other paper</a>. An OCL tool aiming at supporting the refactoring of OCL |
| expressions is <a href="http://www.roclet.org/">RoclET</a>.</li> |
| |
| <li>So far <i>rule engines</i> have been reluctant to adopt OCL as |
| notation for specifying the <i>activation condition</i> that triggers |
| the <i>action part</i> of a reactive rule. We see no major technical |
| difficulty in replacing this proprietary portion of rule languages with |
| standard OCL.</li> |
| |
| <li>Detecting broken invariants and detecting when an activation |
| condition should trigger are particular cases of the <i>incremental |
| update of materialized views</i>, a topic of interest in all data models. |
| The most efficient algorithms to detect these situations have been |
| designed for relational DBMSs. Work in this area for OCL includes the |
| PhD thesis by <a |
| href="http://www.lsi.upc.edu/~jcabot/research/IncrementalOCL/index.html">Jordi |
| Cabot</a>, and <a |
| href="http://www.simula.no/departments/engineering/publications/SE.7.Briand.2004">a |
| master thesis</a> on using AspectJ to instrument OCL contracts at runtime |
| (by <a href="http://www.simula.no/portal_memberdata/jamesdz">James |
| Dzidek</a>).</li> |
| </ul> |
| |
| <p>The examples above are just a glimpse of on-going work involving |
| processing of Abstract Syntax Trees of OCL (in particular) and of |
| software models in general. The availability of OCL infrastructure as |
| provided by MDT OCL, together with contributions from the community, is |
| a step forward towards the widespread availability of reliable, |
| standards-based model-compiler technology. The building blocks for this |
| promising area are also at your disposal.</p> |
| |
| |
| <h2>Appendix A: Class model of Royal & Loyal</h2> |
| |
| <p>The class model of the <a href="./files/RandL.ecore">Royal & |
| Loyal</a> case study is shown for reference purposes below:</p> |
| |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img src="images/RandL/RandL.png" |
| alt="Royal and Loyal class model "></td> |
| </tr> |
| <caption align="bottom"><b>Figure 18</b> Royal & Loyal class |
| model</caption> |
| </table> |
| |
| <h2>Appendix B: Comparison with XMI Tree Visualization</h2> |
| |
| <p>OCL ASTs can be serialized to <tt>.xmi</tt> format from the OCL |
| Interpreter console and then visualized with the EMF-provided XMI |
| editor. In detail:</p> |
| <ul> |
| <li>type an OCL expression in the OCL Interpreter console</li> |
| <li>save it (Save last evaluated expression to an XMI file on |
| the toolbar view)</li> |
| <li>bring that file to the workspace</li> |
| <li>open it with the Sample Reflective Ecore Model Editor</li> |
| </ul> |
| |
| <p>For the invariant shown in Figure 1, the result of the above |
| looks as follows (Figure 19):</p> |
| |
| <table border="0" cellpadding="8"> |
| <tr> |
| <td><img |
| src="images/myPNG/savingAnOCLASTasXMIandVisualizingIt.PNG" |
| alt="savingAnOCLASTasXMIandVisualizingIt"></td> |
| </tr> |
| <caption align="bottom"><b>Figure 19</b> Visualization of an |
| <tt>.xmi</tt> prepared with OCL Interpreter</caption> |
| </table> |
| |
| <p>A comparison with Figure 1 shows that:</p> |
| <ul> |
| <li>information about typing for the expression elements can be |
| found only in the Properties view, thus forcing to navigate between two |
| screen locations</li> |
| <li>the role played by each sub-expression (be it an argument, a |
| source expression, a new variable that will be visible in sub-scopes) |
| is not clear from the XMI editor. Instead, OCLASTView shows nodes |
| labelled with this OCL-specific information</li> |
| <li>OCLASTView can be easily extended to depict additional |
| information (e.g. which variables constitute the current scope at |
| different AST nodes). To reconstruct this information with an XMI |
| viewer, a cumbersome parsing of XML elements would be necessary |
| (cumbersome because the symbol tables prepared by the OCL parser are |
| not available anymore, and thus have to be in effect reconstructed)</li> |
| </ul> |
| |
| <p>Specially the last item sums up the differences between both data |
| structures.</p> |
| |
| <h2>References</h2> |
| |
| <ul> |
| <li>MDT OCL: <a |
| href="http://www.eclipse.org/modeling/mdt/downloads/?project=ocl">OCL |
| SDK Download</a> (includes on-line Developer Guide and Interactive OCL |
| Console example)</li> |
| </ul> |
| |
| <ul> |
| <li>OCL 2.0: <a |
| href="http://www.omg.org/cgi-bin/doc?formal/2006-05-01">Specification</a> |
| </li> |
| </ul> |
| |
| <ul> |
| <li><a |
| href="http://www.eclipse.org/modeling/mdt/?project=uml2#uml2">UML2</a> |
| : an EMF-based implementation of the UML<sup>TM</sup> 2.x metamodel for |
| the Eclipse platform.</li> |
| </ul> |
| |
| <ul> |
| <li><a |
| href="http://www.eclipse.org/modeling/mdt/?project=uml2tools#uml2tools">UML2 |
| Tools</a> : a set of GMF-based editors for viewing and editing UML models. |
| </li> |
| </ul> |
| |
| <ul> |
| <li>Christian W. Damus shows in his article <a |
| href="http://www.eclipse.org/articles/article.php?file=Article-EMF-Codegen-with-OCL/index.html">Implementing |
| Model Integrity in EMF with MDT OCL</a> how to have Java method bodies |
| generated from OCL constraints (invariants, derived properties and |
| derived operations) specified in an Ecore-based model.</li> |
| </ul> |
| |
| <ul> |
| <li>Ed Merks and Marcelo Paternostro explain in the EclipseCon |
| 2007 talk <a |
| href="http://www.eclipsecon.org/2007/index.php?page=sub/&id=3845">Modeling |
| Generics with Ecore</a> the changes in Ecore that allow it to model a |
| generic type system.</li> |
| </ul> |
| |
| <h2>Acknowledgements</h2> |
| |
| <p>The visitor for simplifying arithmetic expressions presented here |
| is based on work by <a href="http://www.avenzo.com ">Veronica |
| Tedjasukmana</a> (for another OCL tool) on a family of visitors that cover a |
| larger set of simplification rules, for both arithmetic and boolean |
| operations.</p> |
| |
| |
| <h2>Source Code</h2> |
| |
| <p>For running this plug-in, just copy the provided <tt>.jar</tt> of |
| the <a href="./install/plugins/OCLASTView_1.0.0.jar">OCLASTView plug-in</a> into your <tt><ECLIPSE_INSTALL>/plugins</tt> |
| folder, and restart Eclipse (with <tt>eclipse.exe -clean</tt> to be <i>really |
| sure</i> that the just added plug-in will be picked-up in the product |
| configuration).</p> |
| |
| <p>MDT OCL 1.1 is required. Depending on whether you'll want to edit |
| Ecore or UML models you'll also need EMF 2.3 or UML2 2.x.</p> |
| |
| <p>Source code is provided in the plug-in itself. After the plug-in |
| has been installed, the source code can be imported into the workspace |
| as an Eclipse project with File > Import > Plug-ins and Fragments |
| > Projects with source folders > OCLASTView.</p> |
| |
| <p>If you want to take a look at the source code before actually |
| installing the plug-in, unpack the plug-in jar and take a look inside |
| the <tt>src</tt> folder.</p> |
| |
| </div> |
| |
| <div class="notices"> |
| <h2>Notices</h2> |
| Java and all Java-based trademarks and logos are trademarks or |
| registered trademarks of Sun Microsystems, Inc. in the United States, |
| other countries, or both.<br> |
| IBM is a registered trademark of International Business Machines |
| Corporation in the United States, other countries, or both.<br> |
| Other company, product, or service names may be trademarks or service |
| marks of others.</div> |
| |
| </body> |
| </html> |