blob: 4ac1312daad807ff088384c9794fe1c0d9c39be5 [file] [log] [blame]
h2(#OCLinEcoreTutorial). OCLinEcore tutorial
This tutorial was updated for Eclipse Indigo; Eclipse 3.7, EMF 2.7, OCL 3.1.
* Since it was prepared before release, the precise 3.1.0.v20110nnnn qualification in screenshots is earlier than final release.
h3. Overview
In this example you will
* Create an Ecore model using the OCLinEcore text editor
* Create a dynamic instance of that Ecore model
* Enrich the Ecore model with OCL using the OCLinEcore text editor
* Validate the model and observe the OCL enrichments
* Use the Interactive OCL Console to execute the OCL enrichments
The above is all performed without generating any Java code;
the models exploit EMF's dynamic capabilities and the OCL integration.
You may then
* Create an Ecore genmodel
* Generate Java code for the Ecore model that invokes the OCL expressions.
h3. References
This tutorial assumes that the reader is familiar with generating models using EMF.
The reader is referred to "Generating an EMF Model":../../org.eclipse.emf.doc/tutorials/clibmod/clibmod.html.
Other references:
* The Object Constraint Language: Getting Your Models Ready for MDA. Jos Warmer and Anneke Kleppe. (Addison-Wesley Object Technology)
* "OCL specification":http://www.omg.org/technology/documents/modeling_spec_catalog.htm#OCL.
* "OCLinEcore wiki page":http://wiki.eclipse.org/MDT/OCLinEcore.
h3(#Installation). Installing the Eclipse OCL Examples
The OCLinEcore editor is not part of the core OCL functionality included in the
Eclipse Modeling Tools Package, so although you may have OCL installed and be able
to read this tutorial via the *Help->Help Contents->OCL Documentation*, you may
not have the OCL examples installed.
An easy way to test whether you have the OCL Examples installed is
to right click on a *.ecore file and see whether *OCLinEcore (Ecore) Editor*
appears in the *Open With* submenu.
If OCL is not installed at all, or if just the examples are not installed,
the following installation step will automatically install the OCL Examples
and all required projects such as *EMF*, *UML2*, *MWE2*, *Xpand*
and *Xtext*.
Left-click on *Help* in the title-bar then left-click on *Install New Software...*
and select the *Indigo - http://download.eclipse.org/releases/indigo* update site
from the pull-down menu to *Work with* and be patient while the available updates
are identified. Then select *OCL Examples and Editors* from the *Modeling*
category.
!{width:50%}images/4100-install_software_top.png(Install Software Top Half)!
!{width:50%}images/4100-install_software_bottom.png(Install Software Bottom Half)!
Select *Next*.
!{width:50%}images/4100-install_details.png(Install Details)!
Select *Next* again and read the license agreement. Set to accept it.
!{width:50%}images/4100-install_license.png(Install License)!
Select *Finish* and be patient while the software is downloaded and installed.
Select *Restart Now* when prompted to do so.
h3. Troubleshooting
Eclipse Modeling Projects have a large number of classes and so require a
large amount of PermGen space on a Sun JVM. If you are using default Eclipse
startup settings you are liable to encounter OutOfMemoryExceptions. Therefore
follow the advice in "How do I start Eclipse":http://wiki.eclipse.org/IRC_FAQ#How_do_I_start_Eclipse.3F
and set XX:PermSize to at least 64M, either on your Eclipse command line, or your
Eclipse shortcut or in the *eclipse.ini* adjacent to *eclipse.exe*.
The editor currently provides syntax and semantic validation. It does not yet apply
the well-formedness validation, so some problems may be unreported. 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.
h3. Using the OCLinEcore text editor for Ecore
There are many different (compatible) ways to create and edit Ecore models.
* An Ecore Model may be created from an XSD schema file
* An Ecore Model may be created from a Rose model file
* An Ecore Model may be created from annotated Java file
* The Sample Ecore Editor provides tree editing
* The Ecore Tools project provides graphical editing
* Papyrus provides UML editing that may be converted to Ecore
Here we introduce the OCLinEcore editor that provides text editing, which is
appropriate when a non-trivial amount of OCL enrichment is required.
All the above approaches update a *.ecore file, so the user is free to choose
whichever editing approach is best suited for the planned changes.
h4. Create a New EMF Project
We will first create a new project for this example; so invoke *File->New->Project...*
(left-click the *File* menu, then left-click *New*, then left-click *Project...*).
In the *New Project* dialog left-click to expand *Eclipse Modeling Framework*, then left-click to select
*Empty EMF Project*.
!{width:50%}images/4100-new_project.png(New Project)!
Left-click on *Next* and in the *New Empty EMF Project* dialog type *Tutorial* as the project name.
!{width:50%}images/4100-new_empty_emf_project.png(New Empty EMF Project)!
Left-click on *Finish*.
h4. Create a New Ecore Model
We will now create a new model for this example.
With many alternative editors for *.ecore files, the Eclipse platform is not always sure which to use; it seems to prefer the OCLinEcore editor over the Sample Ecore Editor, so there is an easy and harder way to create a new file.
For either approach, first right-click on the *model* folder
in the *Tutorial* project to define the target folder and pop-up the context-sensitive menu.
The easy was is to select *New->File...* and enter *Tutorial.ecore*. If this opens up a text editor showing "package Tutorial" ... then the easy way works. You may skip the 'harder way' since you have already successfully opened your Ecore file with the OCLinEcore editor.
The harder way is to select *New->Other...*.
In the *New* dialog left-click to expand *Eclipse Modeling Framework*, then left-click to select
*Ecore Model*.
!{width:50%}images/4100-new_ecore_model.png(New Ecore Model)!
Left-click on *Next* and then in the *New Ecore Model* dialog type *Tutorial.ecore* as the file name.
!{width:50%}images/4100-new_ecore_model_dialog.png(New Ecore Model Dialog)!
Left-click on *Finish*; The *Sample Ecore* editor for *Tutorial.ecore* may open showing a tree view of a single unnamed @EPackage@. Alternatively the *OCLinEcore* editor may be opened by default, so you can skip the next change-editor step.
!{width:50%}images/4100-empty_ecore.png(Empty Ecore Editor)!
Close the editor by left-clicking the cross on the editor tab.
h4(#OCLinEcoreMetamodel). Edit Ecore Model as OCLinEcore
We will now open the Ecore model using the OCLinEcore text editor and provide some
initial content.
Right-click on the *Tutorial.ecore* file to pop-up the context-sensitive menu
and select *Open With->OCLinEcore (Ecore) Editor*.
An almost empty text file appears showing the module, the package keyword and an empty name and conbsequently an error.
!{width:50%}images/4100-empty_oclinecore.png(Empty OCLinEcore Editor)!
Now type (or cut and paste) the following text into the editor and save the file.
!images/4100-metamodel.png(Example Metamodel)!
"[Text for cut and paste]":../references/4100-metamodel.oclinecore
The syntax is defined in "OCLinEcore":#OCLinEcore. It emulates OMG specifications with
'name : type[multiplicity] { properties }'.
* @import@ associates an alias with an external EPackage.
* @package@ introduces an EPackage with name, nsPrefix and nsURI.
* @class@ introduces an EClass with name and optional superclasses.
* @attribute@ introduces a property with a datatype type (an EAttribute).
* @property@ introduces a property with a class type (an EReference).
* @#@ introduces an opposite role name.
* @_'xxx'@ escapes an awkward or reserved word identifier.
The import URI is the URI of a Package, so in the example the @http://www.eclipse.org/emf/2002/Ecore@
is the URI of the model, @#@ is the fragment separator and @/@ is the path to
the Package at the root of the XMI document.
Completion assist (Ctrl Space) may be used for syntax assistance.
Format (Ctrl-Shift F) may be used to auto-format a selected range.
In order to discover a syntax for which completion assist is insufficient,
you may use the Sample Ecore Editor on a test file to create the kind of Ecore element
that you require, and then open the test file with the OCLinEcore editor to see the
corresponding textual syntax.
h4. The Tutorial Meta-Model
The example meta-model models a library with members and books
and loans of books to members. It may be viewed graphically using the Ecore Tools
(not part of this tutorial).
!{width:50%}images/4100-ecore_diagram.png(Ecore Diagram)!
Note that this diagram is an Ecore Diagram rather than a UML Diagram and so the default multiplicities for attributes is Ecore's [0..1] rather than OCLinEcore's and UML's [1..1].
Note also that the OCL types @String@ and @Integer@ map
to @EString@ and @EBigInteger@ in Ecore.
h3. Create a Dynamic Model Instance
At this point a corresponding EMF tutorial would show how to generate Java code for
the meta-model and an editor for the meta-model. Here we are concerned with modeling, so we will
continue with the models alone.
In order to create a model from the meta-model, we require the meta-model to exist as a file so that both meta-model and model editors can reference it. Therefore save the meta-model to a file by clicking the close cross on the editor tab and answering *Yes* when prompted to save changes. Now reopen the metamodel by selecting *Tutorial.ecore* and selecting *Open With->OCLinEcore (Ecore) editor*.
bq..
It is necessary to explicitly specify *Open With->OCLinEcore (Ecore) editor* once to ensure that the Eclipse platform registers your preference for the OCLinEcore rather than Sample Ecore Editor.
p.
In the outline, double-click on *Library* to select it and then right-click to show the context-sensitive menu
and then left-click on *Create Dynamic Instance...* to start to create a
new Dynamic Model with @Library@ at its root.
(If the Outline is not visible, it may be made visible by *Window->Show View->Outline*.)
(If @Library@ is not visible in the Outline, left-click on *OCLinEcore Document*
to expand it, then on *tutorial* to expand it.)
!{width:50%}images/4100-create_dynamic_instance.png(Create Dynamic Instance)!
In the *Create Dynamic Instance* dialog select *Tutorial/model* as
the parent folder for the *Tutorial.xmi* dynamic model instance and left-click *Finish*.
!{width:50%}images/4100-create_dynamic_instance_dialog.png(Create Dynamic Instance Dialog)!
The model is automatically opened for editing using the Sample Reflective Ecore Editor,
which gives a tree-like presentation of the model. The properties of each node can
be seen in the Properties View.
!{width:50%}images/4100-initial_model.png(Initial Model)!
(If the Properties View is not visible, right-click within the editor and left-click on
*Show Properties View*.)
From the right-button menu for @Library@ use *New Child->Books Book* twice,
use *New Child->Loans Loan* once and *New Child->Members Member* three times
to populate the model with two books, one loan and three members.
Left-click to select each of the Books and Members in turn and enter a name
such as @b1@ or @m2@ using the Properties View. Specify that b1
has one copy and that b2 has 2 copies.
!{width:50%}images/4100-model_copies.png(Model Showing Copies)!
The books and members now have distinct titles in the outline.
When you left-click to select the Loan and edit its Book and Member attributes,
the associated pull-down has meaningful entries. Specify that the Loan is for
@b2@ by @m3@.
!{width:50%}images/4100-model_pull_down.png(Model Pull-Down Menu)!
The configuration so far is simple, three members, two books and one loan. We can
validate that this by right-clicking on the @Library@ node, and left-clicking
to *Validate* @Library@ and all its children.
!{width:50%}images/4100-validate_menu.png(Validate Menu)!
Since the model is so simple, it is difficult to have anything wrong; most of
the illegal modeling options such as a Loan composing rather than referencing a
Book are prevented by the Editor's enforcement of the meta-model.
!{width:50%}images/4100-validation_successful.png(Validation Successful)!
(If you have an error at this point, a *Details* button will lead you to some
diagnostics that may clarify the problem. Pasting the following XMI should also
resolve an entry problem.)
bc..
<?xml version="1.0" encoding="ASCII"?>
<tut:Library xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tut="http://www.eclipse.org/mdt/ocl/oclinecore/tutorial"
xsi:schemaLocation="http://www.eclipse.org/mdt/ocl/oclinecore/tutorial
Tutorial.ecore">
<books name="b1" copies="1"/>
<books name="b2" copies="2"/>
<loans book="//@books.1" member="//@members.2"/>
<members name="m1"/>
<members name="m2"/>
<members name="m3"/>
</tut:Library>
p.
We will now create two further identical loans of @b2@ by @m3@. This
may conveniently be performed by left-clicking to select the existing loan,
typing Ctrl-C to copy it, left-clicking to select the @Library@ as the new parent,
then typing Ctrl-V to paste it on the library. Repeat so that there are three
identical loans.
Validating the library should still be successful, although it is clearly wrong for
the two copies of @b2@ to participate in three loans.
h3. Enrich the meta-model with OCL
The semantic constraint that a book cannot be borrowed more times than there are books
is a simple example of a constraint that cannot be expressed by simple multiplicities;
a more powerful capability is required that may potentially require evaluation
of functions of almost arbitrary complexity. The Object Constraint Language
provides this capability.
The constraint can be realized as an invariant on a book that specifies that
that (the size of the (selection of loans involving the book)) is less than or equal
to (the number of copies of the book).
Close the *Tutorial.xmi* editor before modifying its meta-model. (Beware that
a wide variety of unpleasant errors can occur if the meta-model is changed after
the model is loaded.)
Add the invariant shown below to the meta-model.
!images/4100-metamodel2.png(Example Metamodel with Invariant)!
"[Text for cut and paste]":../references/4100-metamodel2.oclinecore
The required semantic is expressed by the @SufficientCopies@ invariant constraint for a Book.
For a valid model the SufficientCopies invariant must always be true.
If you reopen the *Tutorial.xmi* editor and invoke *Validate* for the @Library@,
you will now get a validation error. Left click *Details* for details.
!{width:50%}images/4100-validation_unsuccessful.png(Validation Unsuccessful)!
The *Details* identifies that the @SufficientCopies@ invariant is not
satisfied for the @b2@ book.
If you now change the first loan so that @b1@ is borrowed and then validate
again, the problem is resolved. It is alright for @m3@ to borrow
the one copy of @b1@ and the two copies of @b2@.
Before introducing a further constraint of no duplicate loans, we will show
how OCL expressions can be exercised. OCL is a very powerful compact language;
the example hides a loop over all the loans. More complex examples may easily
involve three or four levels of hidden loops on a single line, but may equally
easily have simple errors. It is therefore helpful to simplify expressions
and use helper operations and properties to modularise them. These may then be
exercised using the OCL Console.
h3(#OCLinEcoreTutorial-Console). The OCL Console
The OCL Console supports interactive execution of an OCL expression in the
context of a model instance.
To make the OCL Console visible, first make the *Console* view visible by
*Window->Show View->Console*. Then right click on the *Open Console* and
left click on *Interactive OCL*.
!{width:50%}images/4100-ocl_console_menu.png(OCL Console menu)!
Alternatively, you can just invoke *Show OCL Console* from the right button menu
within the *Sample Ecore Editor* or *Sample Reflective Ecore Editor*.
The *Interactive OCL* console comprises two main text panes. The upper pane
displays results. The lower pane supports entry of queries.
Left-click to select the @Library@ in the *Tutorial.xmi* as the context
for a query, and then type @books@ followed by a new line into the lower
pane of the console.
The result of evaluating this query for the Library is shown.
!{width:50%}images/4100-books_query.png(Books Query)!
Substantial OCL queries spanning many lines may be entered and so the cursor up
and cursor down keys move across lines. If you want to access an earlier query,
you may use the *Page Up* or *Page Down* keys to save typing them again.
You can examine the execution of the earlier query by selecting each of the books
in turn and executing @library.loans->select(book=self)@, to see that @b1@
has one Loan and @b2@ two.
h3(#OCLinEcoreTutorialHelpers). Helper Features and Operations
We will now introduce some helper attributes and operations to make
the OCL clearer and provide a richer meta-model API.
Close the *Tutorial.xmi* editor and modify the meta-model to include
the derived @loans@ property and the helper operation @isAvailable()@.
Simplify the invariant to use the derived property.
!images/4100-metamodel3.png(Example Metamodel with Features)!
"[Text for cut and paste]":../references/4100-metamodel3.oclinecore
Note that the derived property must also be volatile to avoid problems when
a model is loaded but has no content.
The derived property is visible in the *Properties* view.
!{width:50%}images/4100-derived_property.png(Derived Property)!
The helper operation can be evaluated in the *Console* view by selecting book @b2@ and typing @isAvailable()@ for execution.
!{width:50%}images/4100-helper_operation.png(Helper Operation)!
We will now add further helpers and constraints to enforce an
at most two loans per member policy and to require loans to be unique.
(Don't forget to close *Tutorial.xmi* while changing its meta-model.)
!images/4100-metamodel4.png(Example Metamodel with More Features)!
"[Text for cut and paste]":../references/4100-metamodel4.oclinecore
The additional @books@ property may be evaluated in the OCL
Console to show which books each member has on loan. The property may also be seen in the *Properties* view.
Select the library again and invoke *Validate* from the right button menu.
There are now two validation failures.
!{width:50%}images/4100-two_validation_errors.png(Two Validation Errors)!
h3. Generating Java Code
We have shown how OCL may be used to enrich Ecore meta-models, how model instances can be created
and validated and how expressions can be evaluated, all without generating any Java code.
Exactly the same facilities are available if you do generate Java code and as a result you gain some speed
benefits. In the Eclipse OCL 3.1.0 (Indigo) release the generated Java code for OCL is
interpreted and so the speed gains occur only for the EMF models. In a future release,
the OCL will be converted to Java giving significant speed improvements.
Generating Java code is exactly the same as for any other EMF project; with one important
difference; you must set *Operation Reflection*
to true.
Select the *Tutorial.ecore* file and invoke *New->Other...* from the right button menu
and select *Eclipse Modeling Framework* and *EMF Generator Model*.
!{width:50%}images/4100-new_emf_generator.png(New EMF Generator)!
Select *Next*.
!{width:50%}images/4100-new_emf_generator_model.png(New EMF Generator Model)!
Select *Next*.
!{width:50%}images/4100-new_emf_generator_model_ecore.png(New EMF Generator Model for Ecore)!
Select *Next*.
!{width:50%}images/4100-new_emf_generator_model_load.png(New EMF Generator Model Load)!
Select *Load* and *Next*.
!{width:50%}images/4100-new_emf_generator_model_packages.png(New EMF Generator Model Packages)!
Select *Finish*.
The *Tutorial.genmodel* editor opens.
!{width:50%}images/4100-gen_model.png(Gen Model)!
Most of the default settings are suitable. The one that is not is highlighted. Select the
root *Tutorial* and scroll down the *Properties* view and set *Operation Reflection*
to true.
You may now invoke *Generate Model Code* from the right button menu of either *Tutorial*
to generate Java models that invoke OCL.
!{width:50%}images/4100-gen_model_menu.png(Gen Model Menu)!
h4. Java Details
You can check that the OCL appears in your Java by looking at *TutorialValidator.java*
where you'll find the OCL expression as a String awaiting compilation at run-time, and
the validate invocation that triggers that compilation and execution.
bc..
protected static final String MEMBER__AT_MOST_TWO_LOANS__EEXPRESSION = "\n" +
"\t\t\tloans->size() <= 2";
public boolean validateMember_AtMostTwoLoans(Member member, DiagnosticChain
diagnostics, Map<Object, Object> context) {
return
validate
(TutorialPackage.Literals.MEMBER,
member,
diagnostics,
context,
"http://www.eclipse.org/emf/2002/Ecore/OCL",
"AtMostTwoLoans",
MEMBER__AT_MOST_TWO_LOANS__EEXPRESSION,
Diagnostic.ERROR,
DIAGNOSTIC_SOURCE,
0);
}
p.
Similarly in *BookImpl* you will find the declaration of a cached delegate and
the dynamic invocation that provokes the first time compilation.
bc..
protected static final EOperation.Internal.InvocationDelegate
IS_AVAILABLE__EINVOCATION_DELEGATE = ((EOperation.Internal)
TutorialPackage.Literals.BOOK___IS_AVAILABLE).getInvocationDelegate();
public boolean isAvailable() {
try {
return (Boolean)
IS_AVAILABLE__EINVOCATION_DELEGATE.dynamicInvoke(this, null);
}
catch (InvocationTargetException ite) {
throw new WrappedException(ite);
}
}
p.
The OCL expression for the invocation delegate may be found in *TutorialPackageImpl.createOCLAnnotations()*.
bc..
addAnnotation
(getBook__IsAvailable(),
source,
new String[] {
"body", "loans->size() < copies"
});
p.
h4. API Invariants
The invariants we have used so far do not contribute to the class API.
If you want to have fine grain control of which validations are performed,
perhaps because in some incremental context not all are appropriate, you
may use the operation form of an invariant.
bc..
class Book
{
operation sufficientCopies(diagnostics : ecore::EDiagnosticChain,
context : ecore::EMap<ecore::EJavaObject,ecore::EJavaObject>) : Boolean
{
body: library.loans->select(book=self)->size() <= copies;
}
attribute name : String;
attribute copies : Integer;
property library#books : Library;
}
p.
Note that the operation must have a Boolean return (true for valid) and
diagnostics and context arguments.
h3. Summary
To illustrate how to work with the OCL and Ecore as models we have
* Created an Ecore meta-model using the OCLinEcore text editor
* Created a dynamic model instance from that meta-model
* Enriched the meta-model with embedded OCL
* Used the embedded OCL while validating the model
* Queried the model usng the Interactive OCL Console.
* Evaluated OCL embedded in the meta-model in the Console.
To use OCL and Ecore as generated Java models we have
* Generated Java that exploits the embedded OCL.