blob: 306ebad1e38876dae6ae29d2c05418b5564834d3 [file] [log] [blame]
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.3.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.3.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.3.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.3.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.