Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "JS4EMF/EMF Delegates"

(Enriching the library example with Javascript)
Line 22: Line 22:
 
[[Image:Initial library model.png|Initial library model]]<br>  
 
[[Image:Initial library model.png|Initial library model]]<br>  
  
We'll start by considering the name attribute of the Person class. A name should be a sequence of letters and spaces, and to express this as a constraint we do the following:  
+
We'll start by considering the '''name''' attribute of the '''Person''' class. A name should be a sequence of letters and spaces, and to express this as a constraint we do the following:  
  
 
*Select the Person class and open the view EMF Delegates View  
 
*Select the Person class and open the view EMF Delegates View  
Line 39: Line 39:
 
As can be seen in the left figure, the Person class has one constraint. In the right figure, we see the corresponding annotations for the nameHasLetterAndSpacesOnly constraint: First, the library package has an annotation that states that we use Javascript for validation. Second, the Person class mentions this constraint as its only constraint. Third, the constraint's Javascript has its own annotation.  
 
As can be seen in the left figure, the Person class has one constraint. In the right figure, we see the corresponding annotations for the nameHasLetterAndSpacesOnly constraint: First, the library package has an annotation that states that we use Javascript for validation. Second, the Person class mentions this constraint as its only constraint. Third, the constraint's Javascript has its own annotation.  
  
=== Derived features for given and family names ===
+
=== Invariant for borrowed books ===
  
The next enrichment will be the derived features '''givenName''' and '''familyName'''. The givenName is supposed to be the first word of the name attribute and the familyName the last, with the familyName taking priority if the name only contains one word. To add the appropriate code, do the following:
+
An alternative to constraints is using invariants. An invariant is similar to a constraing, but is explicitly modelled as a method with a specific signature. This gives better control over how the invariant is used in the validation process. We'll implement the rule that all the books associated with a loan must be have the same owning library as the loan object.
 +
 
 +
*Select the Loan class (and open the EMF Delegates view).
 +
*Select the add invariant in the view's toolbar.
 +
*Provide the name of the operation implementing the invariant.
 +
 
 +
This will create the operation with the appropriate signature (right figure below) and if you may select in and enter the operation's body (left figure below).
  
*Select the givenName (or familyName) feature.
 
*The EMF Delegates view will notice this is a derived feature and let you enter the appropriate Javascript.
 
  
After editing the Javascript, as shown on the left figure below, the appropriate annotations will be automatically added, as shown in the right figure below.<br><br>
 
  
 
{| width="200" cellspacing="1" cellpadding="1" border="1"
 
{| width="200" cellspacing="1" cellpadding="1" border="1"
|+ Derived features for given and family names.
+
|+ Invariant for borrowed books
 
|-
 
|-
 
|  
 
|  
 
|  
 
|  
 
|}
 
|}
 +
 +
=== Derived features for given and family names  ===
 +
 +
The next enrichment will be the derived features '''givenName''' and '''familyName'''. The givenName is supposed to be the first word of the name attribute and the familyName the last, with the familyName taking priority if the name only contains one word. To add the appropriate code, do the following:
 +
 +
*Select the givenName (or familyName) feature.
 +
*The EMF Delegates view will notice this is a derived feature, as indicated in the model, and let you enter the appropriate Javascript.
 +
 +
After editing the Javascript, as shown on the left figure below, the appropriate annotations will be automatically added, as shown in the right figure below.<br><br>
 +
 +
{| width="200" cellspacing="1" cellpadding="1" border="1"
 +
|+ Derived features for given and family names.
 +
|-
 +
| [[Image:Delegates view derived features.png]]
 +
|
 +
[[Image:Ecore model derived features.png]]
 +
 +
|}
 +
 +
=== Operation body for getLoansDueBefore  ===
 +
 +
fd

Revision as of 19:00, 9 May 2011

Enriching Ecore models with Javascript

Ecore models are used for modelling data and among others generating Java code for representing the data. The model includes information about classes and attributes, inheritance and associations, which in effect defines and limits what structures of objects that are valid for the modelled domain. E.g. a model of the domain of libraries and books may express that all Books have a title and an author and is owned by some library. A library may lend books to people (persons) and record the date before which they should be returned. EMF will make sure that all instance data will be correct according to these structural rules. However, since there are limits to what can be directly expressed in Ecore, you can still build invalid data, e.g. give a person a name with illegal characters. The solution is to go outside Ecore and implement data rules in Java and hook it into EMF's validation mechanism. The downside is that these rules are not part of the model and relies on code generation and compilation.

To allow for formulating rules with dynamic languages like Javascript and attaching them to the model, EMF has for some time, supported the integration of language interpreters and attaching scripts to model elements using annotations. Support for OCL (Object Constraint Language) has existed for some time, and now js4emf brings support for Javascript. In addition, js4emf provides UI that makes it easier to get all the annotations right, which can be a bit tricky.

Invariants, constraints, derived features and operation bodies

So what kind of annotations are provided and what are they used for? There are four kinds:

  • Constraints are boolean expressions that are attached to a class (EClass) and will tell if an instance is invalid. These are used for simple checks.
  • Invariants are similar to constraints, but are implemented by methods (EOperations) with a certain signature (return value and parameter list). These are used when you want more control over the validation process.
  • Derived features are features that compute their values from other features. These are used when you want to access values in the same manner, independent of what values are actually stored or computed.
  • Operation bodies are the actual implementation of procedural logic, that you would otherwise write in Java.

Let's look at an example and see how js4emf supports them.

Enriching the library example with Javascript

We'll take the following Ecore model as the starting point:

Initial library model

We'll start by considering the name attribute of the Person class. A name should be a sequence of letters and spaces, and to express this as a constraint we do the following:

  • Select the Person class and open the view EMF Delegates View
  • Select the Add constraint button in the view's toolbar
  • Give the constraint a name, e.g. nameHasLetterAndSpaceOnly

This will add the necessary constraint annotations, and select this constraint so you can edit the constraint's Javascript. The left figure below shows the EMF Delegates view with the appropriate code, while the right figure shows how the Ecore model has been augmented with the appropriate annotations.

A constraint for the name attribute of the Person class
EMF Delegates view with name constraint Ecore model with name constraint

As can be seen in the left figure, the Person class has one constraint. In the right figure, we see the corresponding annotations for the nameHasLetterAndSpacesOnly constraint: First, the library package has an annotation that states that we use Javascript for validation. Second, the Person class mentions this constraint as its only constraint. Third, the constraint's Javascript has its own annotation.

Invariant for borrowed books

An alternative to constraints is using invariants. An invariant is similar to a constraing, but is explicitly modelled as a method with a specific signature. This gives better control over how the invariant is used in the validation process. We'll implement the rule that all the books associated with a loan must be have the same owning library as the loan object.

  • Select the Loan class (and open the EMF Delegates view).
  • Select the add invariant in the view's toolbar.
  • Provide the name of the operation implementing the invariant.

This will create the operation with the appropriate signature (right figure below) and if you may select in and enter the operation's body (left figure below).


Invariant for borrowed books

Derived features for given and family names

The next enrichment will be the derived features givenName and familyName. The givenName is supposed to be the first word of the name attribute and the familyName the last, with the familyName taking priority if the name only contains one word. To add the appropriate code, do the following:

  • Select the givenName (or familyName) feature.
  • The EMF Delegates view will notice this is a derived feature, as indicated in the model, and let you enter the appropriate Javascript.

After editing the Javascript, as shown on the left figure below, the appropriate annotations will be automatically added, as shown in the right figure below.

Derived features for given and family names.
Delegates view derived features.png

Ecore model derived features.png

Operation body for getLoansDueBefore

fd

Back to the top