| |
| h2(#AbstractSyntax). OCL Abstract Syntax Model |
| |
| The OCL Abstract Syntax Model is defined by the |
| "OCL Language 2.4 specification":http://www.omg.org/spec/OCL . |
| We will not attempt to describe this model, here. However, the Eclipse |
| implementation of OCL defines some extensions to this model that provide |
| additional services. The most important of these is support for the |
| _Visitor_ design pattern. |
| |
| !{width:70%}images/5150-ast.png(OCL Visitor API)! |
| |
| h3. The Visitable and Visitor Interfaces |
| |
| All of the metaclasses in the Abstract Syntax Model (nodes in the AST) that can be visited implement the "@Visitable@":http://download.eclipse.org/ocl/javadoc/6.4.0/org/eclipse/ocl/utilities/Visitable.html interface. It define a single operation @accept(Visitor)@. This method delegates to the appropriate @visitXyz(Xyz)@ method of the "@Visitor@":http://download.eclipse.org/ocl/javadoc/6.4.0/org/eclipse/ocl/utilities/Visitor.html . The direct implementors of the @Visitable@ interface are the @OCLExpression@ and those metaclasses of the @Expressions@ package that do not conform to @OCLExpression@: |
| |
| * @Variable@ |
| * @CollectionLiteralPart@ |
| * @TupleLiteralPart@ |
| * @ExpressionInOCL@ |
| |
| This last is not defined in the @Expressions@ package |
| because it pertains to the placement of OCL in @Constraint@ |
| elements in models. |
| |
| The OCL parser, internally, defines a few implementations of visitors, including |
| a @ValidationVisitor@ for validating OCL expressions and an |
| "@EvaluationVisitor@":http://download.eclipse.org/ocl/javadoc/6.4.0/org/eclipse/ocl/EvaluationVisitor.html for evaluating OCL expressions. |
| |
| h3. Implementing a Visitor |
| |
| The best way to implement a visitor is to extend the |
| "@AbstractVisitor@":http://download.eclipse.org/ocl/javadoc/6.4.0/org/eclipse/ocl/utilities/AbstractVisitor.html class. It provides a @result@ variable of the generic |
| type parameter type @T@ to store the result computed |
| by the visitor (optional) and a convenient pattern of selective method overrides |
| to process only those nodes of interest for the task at hand. |
| |
| The @AbstractVisitor@ provides implementations of all |
| of the @visitXyz()@ interface methods that simply |
| return the current @result@ value. Furthermore, for |
| any internal nodes of the syntax tree (such as |
| @OperationCallExp@ and @IfExp@), |
| the @visitXyz()@ methods recursively visit the child |
| nodes, feeding the results of those descents into a @handleXyz()@ |
| method that the subclass can override to compute some result from the child |
| results. |
| |
| Thus, a subclass needs only to selectively override the default implementations |
| of @visitXyz()@ methods for leaf tree nodes and |
| @handleXyz()@ methods for non-leaves. For example, to |
| find all variables that are declared but never used: |
| |
| bc.. |
| OCLExpression<Classifier> expr = getExpression(); // hypothetical source of an expression |
| |
| Set<Variable<Classifier, Parameter>> variables = expr.accept( |
| new AbstractVisitor<Set<Variable<Classifier, Parameter>>, |
| Classifier, Operation, Property, EnumerationLiteral, |
| Parameter, State, CallOperationAction, SendSignalAction, Constraint>( |
| new HashSet<Variable<Classifier, Parameter>>()) { // initialize the result |
| |
| @Override |
| protected Set<Variable<Classifier, Parameter>> handleVariable( |
| Variable<Classifier, Parameter> variable, |
| Set<Variable<Classifier, Parameter>> initResult) { |
| |
| result.add(variable); |
| |
| return result; |
| } |
| |
| @Override |
| public Set<Variable<Classifier, Parameter>> visitVariableExp( |
| VariableExp<Classifier, Parameter> v) { |
| |
| result.remove(v.getReferredVariable()); |
| |
| return result; |
| } |
| }}); |
| |
| Set<String> varNames = new HashSet<String>(); |
| for (Variable<?, ?> next : variables) { |
| varNames.add(next.getName()); |
| } |
| |
| System.out.println("Unused variables: + " varNames); |
| p. |
| |