The OCL Abstract Syntax Model is defined by the OCL 2.0 Specification. 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.
[as SVG]
All of the metaclasses in the Abstract Syntax Model (nodes in the AST) that can be visited implement the Visitable interface. It define a single operation accept(Visitor). This method delegates to the appropriate visitXyz(Xyz) method of the Visitor. The direct implementors of the Visitable interface are the OCLExpression and those metaclasses of the Expressions package that do not conform to OCLExpression:
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 for evaluating OCL expressions.
The best way to implement a visitor is to extend the AbstractVisitor 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:
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);
Copyright (c) 2000, 2007 IBM Corporation and others. All Rights Reserved.