Jump to: navigation, search

Difference between revisions of "OCL/OCLinEcore"

< OCL
(Troubleshooting)
(10 intermediate revisions by 4 users not shown)
Line 1: Line 1:
This page describes functionality available when EMF 2.6.0M4 or later and MDT/OCL 3.0.0M6 or later are installed within Eclipse.
+
This page describes functionality first available in the Helios (Eclipse 3.6) release.
 +
 
 +
A brief example of the editor is followed by the description of the Ecore representation.
 +
 
 +
A tutorial introducing OCL and its integration with Ecore forms part of the OCL
 +
Developer Guide accompanying the OCL release and is available online at
 +
[http://help.eclipse.org OCL Developer Guide].
 +
 
 +
==OCLinEcore Editor==
 +
 
 +
The Sample Ecore Editor is convenient for maintaining a couple of OCL constraints, but it has distinct limitations as an Integrated OCL Development Environment:
 +
* maintenance of the EAnnotations needs care.
 +
* the OCL expression is difficult to read in the Properties View.
 +
* syntactic and semantic errors in the OCL are not detected.
 +
 
 +
The OCLinEcore Editor overcomes these limitations. The Editor is available for use with MDT/OCL 3.0.0 by activating the MDT/OCL 3.0.0 Examples functionality.
 +
 
 +
: The Examples functionality may be installed directly using Help->Install New Software from the http://download.eclipse.org/releases/helios site; Select the OCL Examples and Editors Feature from the Modeling category.
 +
 
 +
With the OCLinEcore Editor installed, you may select the Ecore file in a Navigator (Resource Explorer, Package Explorer,...) and invoke Open With->OCLinEcore Editor from the context dependent right button menu. The display should show
 +
 
 +
[[image:OCLinEcore.png]]
 +
 
 +
The above display is the unchanged result of opening Company.ecore.
 +
 
 +
Beware that the editor is very new; there is validation of name references but not of their types; this is work in progress. Sometimes spurious errors are displayed, which may go away with a Save, but may require an editor close and reopen.
 +
 
 +
The OCLinEcore Document may be edited with the aid of syntax and semantic validation and completion suggestions.
 +
 
 +
Whitespace and OCL comments within and surrounding the OCL expressions are persisted in the Ecore EAnnotations. If you want to persist comments outside of the OCL context, invoke SaveAS OclInEcore for the Document root in the Outline.
 +
 
 +
The OCLinEcore uses strict OMG syntax for OCL expressions and an extrapolation of that to the surrounding Ecore. A full write up is TBD. The surrounding syntax of the example editor is open to debate and may change once the editor ceases to be an example in the release after Helios.
  
 
==Ecore Representation==
 
==Ecore Representation==
  
The OCL in Ecore annotations can be maintained directly using the Sample Ecore Editor. An example is shown below.
+
OCL can be embedded in Ecore using annotations. Maintenance of these annotations is performed automatically by the OCLinEcore editor described later. This section explains the underlying representation and so descibes their direct maintenance using the Sample Ecore Editor. An example is shown below.
  
 
[[Image:MDT_OCL_Example_Ecore_Annotations.png|Example OCL in Ecore Annotations]]
 
[[Image:MDT_OCL_Example_Ecore_Annotations.png|Example OCL in Ecore Annotations]]
Line 34: Line 65:
  
 
The delegate value matches an org.eclipse.emf.ecore.invocation_delegate extension point usage in the org.eclipse.ocl.ecore plug-in that provides the delegate functionality. Multiple comma-separated delegates may be specified.
 
The delegate value matches an org.eclipse.emf.ecore.invocation_delegate extension point usage in the org.eclipse.ocl.ecore plug-in that provides the delegate functionality. Multiple comma-separated delegates may be specified.
 +
 +
'''Note:''' When generating the java classes from your genmodel, remember to set the genmodel option 'Operation Reflection' to true. (From EMF 2.8 onwards, 'true' is the default.)
  
 
====Validation Delegate====
 
====Validation Delegate====
Line 127: Line 160:
 
Note that preconditions and postconditions are ignored by MDT/OCL 3.0.0.
 
Note that preconditions and postconditions are ignored by MDT/OCL 3.0.0.
  
==OCL in Ecore Editor==
+
==Registration==
  
The Sample Ecore Editor is convenient for maintaining a couple of OCL constraints, but it has distinct limitations as an Integrated OCL Development Environment:
+
===Plugin===
* maintenance of the EAnnotations needs care.
+
Within Eclipse, the OCL delegate functionality should be provided automatically by the plugin registration
* the OCL expression is difficult to read in the Properties View.
+
provided you have MDT/OCL 3.0 installed. The OCLinEcore editor requires the MDT/OCL Examples to be installed too.
* syntactic and semantic errors in the OCL are not detected.
+
 
+
The OCL in Ecore Editor overcomes these limitations. The Editor will be available for use with MDT/OCL 3.0.0 by activating the MDT/OCL 3.0.0 Examples functionality.
+
 
+
: As of the MDT/OCL 3.0.0M6 release, the Examples functionality may be loaded by using Import Project Set ... for the org.eclipse.ocl/releng/psfs/examples.psf file. The Examples will be available when you start a nested Eclipse session. The import will load required parts of EMF Transaction, EMF Validation and IMP Runtime. If you already have these loaded as plugins, you may edit the examples.psf file to avoid importing them, or just delete them after importing. IMP Runtime is loaded from an SVN repository and so you should have subclipse installed from the http://subclipse.tigris.org/update_1.6.x update site. If you use subversive rather than subclipse, edit the comments at the end of examples.psf.
+
 
+
: It is hoped that a suitable IMP Runtime release will be available shortly on its Update Site so that as from MDT/OCL 3.0.0M7, the Examples will form part of the main MDT/OCL build and be available from the MDT/OCL Update Site.
+
 
+
With the OCL in Ecore Editor installed, you may select the Ecore file in a Navigator (Resource Explorer, Package Explorer,...) and invoke Open With->OCL in Ecore Editor from the context dependent right button menu. The display should show (with syntax coloring)
+
  
 +
===Standalone===
 +
If running standalone, you need to register the OCL delegates by hand, using code such as:
 
<pre>
 
<pre>
package company
+
import org.eclipse.emf.ecore.EOperation;
 +
import org.eclipse.emf.ecore.EStructuralFeature;
 +
import org.eclipse.emf.ecore.EValidator;
 +
import org.eclipse.ocl.ecore.delegate.OCLDelegateDomain;
 +
import org.eclipse.ocl.ecore.delegate.OCLInvocationDelegateFactory;
 +
import org.eclipse.ocl.ecore.delegate.OCLSettingDelegateFactory;
 +
import org.eclipse.ocl.ecore.delegate.OCLValidationDelegateFactory;
  
context Company::size : CompanySizeKind
+
String oclDelegateURI = OCLDelegateDomain.OCL_DELEGATE_URI;
derive:
+
EOperation.Internal.InvocationDelegate.Factory.Registry.INSTANCE.put(oclDelegateURI,
let table : Set(Tuple(range : Sequence(Integer), size : CompanySizeKind)) =
+
new OCLInvocationDelegateFactory.Global());
    Set{
+
EStructuralFeature.Internal.SettingDelegate.Factory.Registry.INSTANCE.put(oclDelegateURI,
Tuple{range=Sequence{0..49}, size=CompanySizeKind::small},
+
new OCLSettingDelegateFactory.Global());
        Tuple{range=Sequence{50..999}, size=CompanySizeKind::medium},
+
EValidator.ValidationDelegate.Registry.INSTANCE.put(oclDelegateURI,
        Tuple{range=Sequence{1000..1000000}, size=CompanySizeKind::large}}
+
new OCLValidationDelegateFactory.Global());
    in table->any(range->includes(employees->size())).size
+
</pre>
  
context Employee
+
(An initialization routine will be provided in a future release.)
inv mustHaveName:
+
not name.oclIsUndefined()
+
 
+
context Employee
+
inv noManagerImpliesDirectReports:
+
manager.oclIsUndefined() implies directReports->size() > 0
+
 
+
context Employee::directReports : OrderedSet(Employee)
+
derive:company.employees->select(manager = self)
+
 
+
context Employee::allReports : Set(Employee)
+
derive:Employee.allInstances()->select(reportsTo(self))
+
 
+
context Employee::reportingChain : OrderedSet(Employee)
+
derive:if (manager.oclIsUndefined()) then OrderedSet{}
+
else manager.reportingChain->prepend(manager)
+
endif
+
 
+
context Employee::reportsTo(manager : Employee) : Boolean
+
body:self.reportingChain->includes(manager)
+
 
+
endpackage
+
</pre>
+
  
This OCL Document may be edited with the aid of syntax and semantic validation and completion suggestions.
+
==Troubleshooting==
  
The Ecore model EAnnotations are updated with each successful analysis of the OCL. The OCL Document should therefore not deviate from the Ecore model for more than a second or two. If the Ecore model is changed externally the OCL Document is immediately refreshed.
+
Problem: I cannot set 'Operation Reflection' to true. / I do not get Java-Code for my OCL method bodys.
  
Whitespace and OCL comments within and surrounding the OCL expressions are persisted in the Ecore EAnnotations.
+
Solution: Ensure that Compliance Level in the genmodel is set to at least 6.0.

Revision as of 06:19, 28 February 2013

This page describes functionality first available in the Helios (Eclipse 3.6) release.

A brief example of the editor is followed by the description of the Ecore representation.

A tutorial introducing OCL and its integration with Ecore forms part of the OCL Developer Guide accompanying the OCL release and is available online at OCL Developer Guide.

OCLinEcore Editor

The Sample Ecore Editor is convenient for maintaining a couple of OCL constraints, but it has distinct limitations as an Integrated OCL Development Environment:

  • maintenance of the EAnnotations needs care.
  • the OCL expression is difficult to read in the Properties View.
  • syntactic and semantic errors in the OCL are not detected.

The OCLinEcore Editor overcomes these limitations. The Editor is available for use with MDT/OCL 3.0.0 by activating the MDT/OCL 3.0.0 Examples functionality.

The Examples functionality may be installed directly using Help->Install New Software from the http://download.eclipse.org/releases/helios site; Select the OCL Examples and Editors Feature from the Modeling category.

With the OCLinEcore Editor installed, you may select the Ecore file in a Navigator (Resource Explorer, Package Explorer,...) and invoke Open With->OCLinEcore Editor from the context dependent right button menu. The display should show

OCLinEcore.png

The above display is the unchanged result of opening Company.ecore.

Beware that the editor is very new; there is validation of name references but not of their types; this is work in progress. Sometimes spurious errors are displayed, which may go away with a Save, but may require an editor close and reopen.

The OCLinEcore Document may be edited with the aid of syntax and semantic validation and completion suggestions.

Whitespace and OCL comments within and surrounding the OCL expressions are persisted in the Ecore EAnnotations. If you want to persist comments outside of the OCL context, invoke SaveAS OclInEcore for the Document root in the Outline.

The OCLinEcore uses strict OMG syntax for OCL expressions and an extrapolation of that to the surrounding Ecore. A full write up is TBD. The surrounding syntax of the example editor is open to debate and may change once the editor ceases to be an example in the release after Helios.

Ecore Representation

OCL can be embedded in Ecore using annotations. Maintenance of these annotations is performed automatically by the OCLinEcore editor described later. This section explains the underlying representation and so descibes their direct maintenance using the Sample Ecore Editor. An example is shown below.

Example OCL in Ecore Annotations

The relevant annotations (a purple dumbbell with a paperclip) may be added by selecting New Child->EAnnotation and then New Child->Details Entry.

EPackage configuration

The embedded OCL becomes active when the appropriate delegate functionality is specified. In practice all three functionalities should be specified. This specification provides EMF with the required configuration information to access the extended functionality provided by these delegates.

Setting Delegate

The setting delegate functionality enables OCL expressions to define initial or derived value of an EStructuralFeature. Thus when eGet(CompanyPackage.Literals.COMPANY__SIZE) or Company.getSize() is invoked the OCL expression is evaluated to provide the value. In an OCL context, the corresponding eSet or setSize is not applicable.

The setting delegate is specified by an EPackage EAnnotation with:
Source = "http://www.eclipse.org/emf/2002/Ecore"
Key = "settingDelegates"
Value = "http://www.eclipse.org/emf/2002/Ecore/OCL"

The delegate value matches an org.eclipse.emf.ecore.setting_delegate extension point usage in the org.eclipse.ocl.ecore plug-in that provides the delegate functionality. Multiple comma-separated delegates may be specified.

Invocation Delegate

The invocation delegate functionality enables OCL expressions to define the body of an EOperation. Thus when eInvoke(CompanyPackage.Literals.EMPLOYEE__REPORTS_TO) or Employee.reportsTo() is invoked the OCL expression is evaluated to provide the value.

The invocation delegate is specified by an EPackage EAnnotation with:
Source = "http://www.eclipse.org/emf/2002/Ecore"
Key = "invocationDelegates"
Value = "http://www.eclipse.org/emf/2002/Ecore/OCL"

The delegate value matches an org.eclipse.emf.ecore.invocation_delegate extension point usage in the org.eclipse.ocl.ecore plug-in that provides the delegate functionality. Multiple comma-separated delegates may be specified.

Note: When generating the java classes from your genmodel, remember to set the genmodel option 'Operation Reflection' to true. (From EMF 2.8 onwards, 'true' is the default.)

Validation Delegate

The validation delegate functionality enables OCL expressions to define one or more invariants of an EClassifier. Thus when the EValidator is activated to validate the classifier, the OCL expressions are evaluated.

The validation delegate is specified by an EPackage EAnnotation with:
Source = "http://www.eclipse.org/emf/2002/Ecore"
Key = "validationDelegates"
Value = "http://www.eclipse.org/emf/2002/Ecore/OCL"

The delegate value matches an org.eclipse.emf.ecore.validation_delegate extension point usage in the org.eclipse.ocl.ecore plug-in that provides the delegate functionality. Multiple comma-separated delegates may be specified.

EClassifier invariants

Ecore provides two different representation for an OCL invaraint that refines the behavior of an EClassifier. One representation exposes the invariant as part of the EClassifier API.

Each non-API invariant is represented as an EAnnotation for the named OCL-invariant constraint and an EAnnotation to enumerate the invariant names. This form of OCL invariant is called a constraint in Ecore documentation. The invariant does not contribute to the EClassifier API.

Each API invariant is represented by an EOperation for the named OCL-invariant constraint, with an EAnnotation to define the operation body. This form of OCL invariant is called an invariant in Ecore documentation. The EOperation contributes to the EClassifier API allowing it to be invoked by application code; perhaps for incremental re-evaluation of invariants.

non-API invariant

The example shows the specification of the body for the Employee mustHaveName invariant equivalent to the following OCL Document snippet.

context Employee
inv mustHaveName:
not name.oclIsUndefined()

The body is specified by an EClassifier EAnnotation with:
Source = "http://www.eclipse.org/emf/2002/Ecore/OCL"
Key = "mustHaveName"
Value = ...the OCL expression...

and an EClassifier EAnnotation with:
Source = "http://www.eclipse.org/emf/2002/Ecore"
Key = "constraints"
Value = space-separated list of invariant names

API invariant

The example partially shows the specification of the body for the Employee noManagerImpliesDirectReports invariant equivalent to the following OCL Document snippet.

context Employee
inv noManagerImpliesDirectReports:
manager.oclIsUndefined() implies directReports->size() > 0

There is no need for any EClassifier EAnnotation. The invariant body should be specified as an EOperation body.

The EOperation must have an EBoolean return, and two parameters of type EDiagnosticChain and EMap<EjavaObject, EJavaObject>.

EStructuralFeature initial and derived values

The example shows the specification of a derived value for the Company::size EStructuralFeature equivalent to the following OCL Document snippet.

context Company::size : CompanySizeKind
derive:
let table : Set(Tuple(range : Sequence(Integer), size : CompanySizeKind)) =
    Set{
	Tuple{range=Sequence{0..49}, size=CompanySizeKind::small},
        Tuple{range=Sequence{50..999}, size=CompanySizeKind::medium},
        Tuple{range=Sequence{1000..1000000}, size=CompanySizeKind::large}}
    in table->any(range->includes(employees->size())).size

The derived value is specified by an EStructuralFeature EAnnotation with:
Source = "http://www.eclipse.org/emf/2002/Ecore/OCL"
Key = "derivation"
Value = ...the OCL expression...

An initial value may be similarly specified with:
Source = "http://www.eclipse.org/emf/2002/Ecore/OCL"
Key = "initial"
Value = ...the OCL expression...

EOperation bodies, preconditions and postconditions

The example shows the specification of the body for the Employee::reportsTo(Employee) EOperation equivalent to the following OCL Document snippet.

context Employee::reportsTo(manager : Employee) : Boolean
body:self.reportingChain->includes(manager)

The body is specified by an EOperation EAnnotation with:
Source = "http://www.eclipse.org/emf/2002/Ecore/OCL"
Key = "body"
Value = ...the OCL expression...

A precondition or postcondition may be similarly specified using "precondition" or "postcondition" as the Key.

Note that preconditions and postconditions are ignored by MDT/OCL 3.0.0.

Registration

Plugin

Within Eclipse, the OCL delegate functionality should be provided automatically by the plugin registration provided you have MDT/OCL 3.0 installed. The OCLinEcore editor requires the MDT/OCL Examples to be installed too.

Standalone

If running standalone, you need to register the OCL delegates by hand, using code such as:

import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EValidator;
import org.eclipse.ocl.ecore.delegate.OCLDelegateDomain;
import org.eclipse.ocl.ecore.delegate.OCLInvocationDelegateFactory;
import org.eclipse.ocl.ecore.delegate.OCLSettingDelegateFactory;
import org.eclipse.ocl.ecore.delegate.OCLValidationDelegateFactory;

String oclDelegateURI = OCLDelegateDomain.OCL_DELEGATE_URI;
EOperation.Internal.InvocationDelegate.Factory.Registry.INSTANCE.put(oclDelegateURI,
	new OCLInvocationDelegateFactory.Global());
EStructuralFeature.Internal.SettingDelegate.Factory.Registry.INSTANCE.put(oclDelegateURI,
	new OCLSettingDelegateFactory.Global());
EValidator.ValidationDelegate.Registry.INSTANCE.put(oclDelegateURI,
	new OCLValidationDelegateFactory.Global());

(An initialization routine will be provided in a future release.)

Troubleshooting

Problem: I cannot set 'Operation Reflection' to true. / I do not get Java-Code for my OCL method bodys.

Solution: Ensure that Compliance Level in the genmodel is set to at least 6.0.