<html> | |
<head> | |
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> | |
<title>OCL Abstract Syntax Model</title> | |
<link href="book.css" rel="stylesheet" type="text/css"> | |
<meta content="DocBook XSL Stylesheets V1.75.1" name="generator"> | |
<link rel="home" href="index.html" title="OCL Documentation"> | |
<link rel="up" href="ProgrammersGuide.html" title="Classic Ecore/UML Programmers Guide"> | |
<link rel="prev" href="ContentAssistSupport.html" title="Content Assist Support"> | |
<link rel="next" href="CustomizingtheEnvironment.html" title="Customizing the Environment"> | |
</head> | |
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"> | |
<h1 xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0">OCL Abstract Syntax Model</h1> | |
<div class="section" title="OCL Abstract Syntax Model"> | |
<div class="titlepage"> | |
<div> | |
<div> | |
<h2 class="title" style="clear: both"> | |
<a name="AbstractSyntax"></a>OCL Abstract Syntax Model</h2> | |
</div> | |
</div> | |
</div> | |
<p>The OCL Abstract Syntax Model is defined by the | |
<a class="ulink" href="http://www.omg.org/spec/OCL" target="_new">OCL Language 2.4 specification</a> . | |
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 | |
<span class="emphasis"><em>Visitor</em></span> design pattern. | |
</p> | |
<p> | |
</p> | |
<div class="mediaobject"> | |
<img src="images/5150-ast.png"></div> | |
<p> | |
</p> | |
<div class="section" title="The Visitable and Visitor Interfaces"> | |
<div class="titlepage"> | |
<div> | |
<div> | |
<h3 class="title"> | |
<a name="TheVisitableandVisitorInterfaces"></a>The Visitable and Visitor Interfaces</h3> | |
</div> | |
</div> | |
</div> | |
<p>All of the metaclasses in the Abstract Syntax Model (nodes in the AST) that can be visited implement the | |
<a class="ulink" href="http://download.eclipse.org/ocl/javadoc/6.4.0/org/eclipse/ocl/utilities/Visitable.html" target="_new"> | |
<code class="code">Visitable</code> | |
</a> interface. It define a single operation | |
<code class="code">accept(Visitor)</code>. This method delegates to the appropriate | |
<code class="code">visitXyz(Xyz)</code> method of the | |
<a class="ulink" href="http://download.eclipse.org/ocl/javadoc/6.4.0/org/eclipse/ocl/utilities/Visitor.html" target="_new"> | |
<code class="code">Visitor</code> | |
</a> . The direct implementors of the | |
<code class="code">Visitable</code> interface are the | |
<code class="code">OCLExpression</code> and those metaclasses of the | |
<code class="code">Expressions</code> package that do not conform to | |
<code class="code">OCLExpression</code>: | |
</p> | |
<div class="itemizedlist"> | |
<ul class="itemizedlist" type="disc"> | |
<li class="listitem"> | |
<p> | |
<code class="code">Variable</code> | |
</p> | |
</li> | |
<li class="listitem"> | |
<p> | |
<code class="code">CollectionLiteralPart</code> | |
</p> | |
</li> | |
<li class="listitem"> | |
<p> | |
<code class="code">TupleLiteralPart</code> | |
</p> | |
</li> | |
<li class="listitem"> | |
<p> | |
<code class="code">ExpressionInOCL</code> | |
</p> | |
</li> | |
</ul> | |
</div> | |
<p>This last is not defined in the | |
<code class="code">Expressions</code> package | |
because it pertains to the placement of OCL in | |
<code class="code">Constraint</code> | |
elements in models. | |
</p> | |
<p>The OCL parser, internally, defines a few implementations of visitors, including | |
a | |
<code class="code">ValidationVisitor</code> for validating OCL expressions and an | |
<a class="ulink" href="http://download.eclipse.org/ocl/javadoc/6.4.0/org/eclipse/ocl/EvaluationVisitor.html" target="_new"> | |
<code class="code">EvaluationVisitor</code> | |
</a> for evaluating OCL expressions. | |
</p> | |
</div> | |
<div class="section" title="Implementing a Visitor"> | |
<div class="titlepage"> | |
<div> | |
<div> | |
<h3 class="title"> | |
<a name="ImplementingaVisitor"></a>Implementing a Visitor</h3> | |
</div> | |
</div> | |
</div> | |
<p>The best way to implement a visitor is to extend the | |
<a class="ulink" href="http://download.eclipse.org/ocl/javadoc/6.4.0/org/eclipse/ocl/utilities/AbstractVisitor.html" target="_new"> | |
<code class="code">AbstractVisitor</code> | |
</a> class. It provides a | |
<code class="code">result</code> variable of the generic | |
type parameter type | |
<code class="code">T</code> 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. | |
</p> | |
<p>The | |
<code class="code">AbstractVisitor</code> provides implementations of all | |
of the | |
<code class="code">visitXyz()</code> interface methods that simply | |
return the current | |
<code class="code">result</code> value. Furthermore, for | |
any internal nodes of the syntax tree (such as | |
<code class="code">OperationCallExp</code> and | |
<code class="code">IfExp</code>), | |
the | |
<code class="code">visitXyz()</code> methods recursively visit the child | |
nodes, feeding the results of those descents into a | |
<code class="code">handleXyz()</code> | |
method that the subclass can override to compute some result from the child | |
results. | |
</p> | |
<p>Thus, a subclass needs only to selectively override the default implementations | |
of | |
<code class="code">visitXyz()</code> methods for leaf tree nodes and | |
<code class="code">handleXyz()</code> methods for non-leaves. For example, to | |
find all variables that are declared but never used: | |
</p> | |
<div class="literallayout"> | |
<p> | |
<code class="code">OCLExpression<Classifier> expr = getExpression(); // hypothetical source of an expression<br> | |
<br> | |
Set<Variable<Classifier, Parameter>> variables = expr.accept(<br> | |
new AbstractVisitor<Set<Variable<Classifier, Parameter>>,<br> | |
Classifier, Operation, Property, EnumerationLiteral,<br> | |
Parameter, State, CallOperationAction, SendSignalAction, Constraint>(<br> | |
new HashSet<Variable<Classifier, Parameter>>()) { // initialize the result<br> | |
<br> | |
@Override<br> | |
protected Set<Variable<Classifier, Parameter>> handleVariable(<br> | |
Variable<Classifier, Parameter> variable,<br> | |
Set<Variable<Classifier, Parameter>> initResult) {<br> | |
<br> | |
result.add(variable);<br> | |
<br> | |
return result;<br> | |
}<br> | |
<br> | |
@Override<br> | |
public Set<Variable<Classifier, Parameter>> visitVariableExp(<br> | |
VariableExp<Classifier, Parameter> v) {<br> | |
<br> | |
result.remove(v.getReferredVariable());<br> | |
<br> | |
return result;<br> | |
}<br> | |
}});<br> | |
<br> | |
Set<String> varNames = new HashSet<String>();<br> | |
for (Variable<?, ?> next : variables) {<br> | |
varNames.add(next.getName());<br> | |
}<br> | |
<br> | |
System.out.println("Unused variables: + " varNames);<br> | |
</code> | |
</p> | |
</div> | |
<p></p> | |
</div> | |
<div class="section" title="The OppositePropertyCallExp Extension"> | |
<div class="titlepage"> | |
<div> | |
<div> | |
<h3 class="title"> | |
<a name="HiddenOpposites"></a>The OppositePropertyCallExp Extension</h3> | |
</div> | |
</div> | |
</div> | |
<p>In Ecore models, a reference may have defined an | |
<code class="code">opposite</code> reference, usually owned by the class that is | |
the type of the forward reference. An opposite reference has several, often undesirable or even | |
prohibitive, implications on the class owning it: | |
</p> | |
<div class="itemizedlist"> | |
<ul class="itemizedlist" type="disc"> | |
<li class="listitem"> | |
<p>A getter and, for settable features with upper multiplicity 1, a setter will be added, requiring the class to know the class owning the forward reference. This would create cyclic component references if the two classes lived in different components and would therefore not be possible.</p> | |
</li> | |
<li class="listitem"> | |
<p>The default serialization format and usually the storage format for non-default model stores changes to include the opposite reference.</p> | |
</li> | |
</ul> | |
</div> | |
<p>Yet, particularly for expressing constraints over the instance models it is often instrumental | |
to be able to navigate such forward references also in reverse. The | |
<code class="code">OppositePropertyCallExp</code> | |
class which inherits from | |
<code class="code">NavigationCallExp</code> and is sibling of | |
<code class="code">PropertyCallExp</code> allows for this reverse navigation in OCL. It | |
points to the forward reference, and its semantics are to navigate this reference in reverse. | |
</p> | |
<p>To allow for convenient creation of such expressions in the OCL concrete syntax, the standard | |
property call syntax, such as | |
<code class="code">self.x</code> can be used, where | |
<code class="code">x</code> | |
is not the name of a forward reference on | |
<code class="code">self</code>'s class but rather | |
an annotated name on a reference using | |
<code class="code">self</code>'s class or any of its | |
base classes as its type. To enable this feature, use the special environment factory class | |
<code class="code">EcoreEnvironmentFactoryWithHiddenOpposites</code> when initializing the | |
OCL environment, e.g., by passing such an object to the | |
<code class="code">OCL.newInstance(...)</code> | |
method. | |
</p> | |
<p>The name for the reverse navigation can be specified by an | |
<a class="ulink" href="http://download.eclipse.org/modeling/emf/emf/javadoc/2.6.0/org/eclipse/emf/ecore/EAnnotation.html" target="_new"> | |
<code class="code">EAnnotation</code> | |
</a> with | |
source | |
<code class="code">http://schema.omg.org/spec/MOF/2.0/emof.xml</code> and with | |
details key | |
<code class="code">Property.oppositeRoleName</code>. The details value | |
contains the name by which the “hidden” opposite can be referred to in OCL | |
expressions. | |
</p> | |
<p>If OCL delegates are to be used, the standard EPackage annotations with | |
<code class="code">invocationDelegate</code>, | |
<code class="code">settingDelegate</code> and | |
<code class="code">validationDelegate</code> details for the | |
<code class="code">http://www.eclipse.org/emf/2002/Ecore</code> source must be augmented as shown by a further | |
<code class="code">hiddenOpposites</code> detail for the | |
<code class="code">http://www.eclipse.org/emf/2002/Ecore/OCL</code> source. | |
</p> | |
<p> | |
</p> | |
<div class="mediaobject"> | |
<img src="images/5155-hidden-opposites.png"></div> | |
<p> | |
</p> | |
<p>This additional annotation causes the | |
<code class="code">EnvironmentFactory</code> | |
functionality for the EPackage to be provided by an instance of the | |
<code class="code">EcoreEnvironmentFactoryWithHiddenOpposites</code> class | |
which uses the | |
<code class="code">DefaultOppositeEndFinder</code> class will be used for finding | |
and navigating the hidden opposites. More substantial customisation is possible by specifying | |
an | |
<code class="code">environmentFactoryClass</code> detail with the fully qualified | |
name of a derived | |
<code class="code">EcoreEnvironmentFactory</code> that | |
provides a constructor taking an | |
<code class="code">EPackage.Registry</code> argument. | |
Note, that the class specified must be visible by your Ecore model’s bundle. | |
</p> | |
</div> | |
</div> | |
</body> | |
</html> |