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

GEMS EMF Intelligence Tutorial

This tutorial presents the basic usage of the GEMS EMF Intelligence framework. Before starting the tutorial, please download and install GEMS EMF Intelligence from http://www.eclipse.org/gmt/gems/download.php. The source code for the tutorial is also available at the GEMS EMF Intelligence download site.

GEMS EMF Intelligence is a framework designed to help you reason about your EMF models. The framework provides a knowledge base that you can assert EMF modeling elements into. Once modeling elements are asserted into the knowledge base, you can add constraints to relationships between model elements. Finally, you can use GEMS EMF Intelligence to derive valid endpoints (other objects in the knowledge base) for relationships of a modeling element.

What is a relationship? One example of a relationship is an EStructuralFeature that refers to another EObject. For example, if we look at the 'Writer' class from the EMF library example:

public interface Writer extends Person
{
  ...
   EList<Book> getBooks();
}

It has a 'books' EStructuralFeature that refers to an EMF Book EClass. The 'books' EStructuralFeature is an example of a relationship between the 'Writer' class and the 'Book' class.

Now, let's look at a very simple example of how to use GEMS EMF Intelligence. Assume that we have an instance of the 'Writer' class but we don't have a list of all of the books that the corresponding author wrote (just one or more). We do, however, have a library full of books and we know that all books from each genre in the library were written by a single author. We can write some constraints to represent this knowledge and use GEMS EMF Intelligence to derive all of the books that any given 'Writer' instance should be associated with.

First, we have to create an EMFIntelligence knowledge base to put the books into:

//First, construct a basic EMFIntelligence knowledge base.
//If you need to use constraints other than OCL, you can
//install them by calling kb.getConstraintEvaluators().put(TYPE, ConstraintEvaluator)
EMFIntelligence kb = new EMFIntelligence();

Now, we can create an OCL constraint to encode our special knowledge about 'Writers' and 'Books' in the library. Our constraint will say that for any 'Book' to be valid for a 'Writer', the 'Writer' must already have at least one 'Book' in its 'books' EStructuralFeature that is in the same category. The OCL constraint:

//Notice that the constraint refers to the variable 'target'.
//The target variable is assigned to item that GEMS EMF Intelligence 
//is testing to see if it can assign to the relationship.
OCLConstraint con1 = new OCLConstraint("self.books->exists( b : Book |    
                                            b.category->includes(target.category))");

GEMS EMF Intelligence constraints have two special variables that are always available 'self' and 'target'. In OCL, 'self' is straightforward since it is a natural part of the language. The variable 'self' contains the object that the constraint is being applied to. Since GEMS EMF Intelligence always applies constraints to relationships as opposed to objects, there are always two objects that the constraint is being applied to. The first object is the object that is the source of the relationship that you pass into GEMS EMF Intelligence asking it to derive the endpoints for. The second object is the potential endpoint for the relationship. The second object is stored in the 'target' variable. Thus, in GEMS EMF Intelligence, all constraints are specified as conditional expressions over the source and target objects (or one or the other...it's up to you).

Now, let's create a few books and an author to test our new constraint:

		
		
//Create a factory so that we can construct books and a writer
EXTLibraryFactory fact = EXTLibraryPackage.eINSTANCE
			.getEXTLibraryFactory();
Book f1 = fact.createBook();
f1.setCategory(BookCategory.MYSTERY_LITERAL);
Book f2 = fact.createBook();
f2.setCategory(BookCategory.BIOGRAPHY_LITERAL);
Book f3 = fact.createBook();
f3.setCategory(BookCategory.MYSTERY_LITERAL);
		
//The writer that we are going to
//query for valid books for
Writer w1 = fact.createWriter();
w1.setFirstName("The Writer of");
w1.setLastName("Mystery");
w1.getBooks().add(f1);
		
//Set the titles of our books
f1.setTitle("Mystery A");
f2.setTitle("Biography B");
f3.setTitle("Mystery C");

Now that we have constructed our 'Books' and 'Writer', we need to add them to the EMFIntelligence knowledge base so that we can use GEMS EMF Intelligence to reason about them:

//Add the books to the knowledge base
kb.add(f1);
kb.add(f2);
kb.add(f3);
		
//Add the writer to the knowledge base
kb.add(w1);

GEMS EMF Intelligence is able to derive valid endpoints for a relationship. To enable GEMS EMF Intelligence to derive valid endpoints for a relationship, we have to tell the knowledge base which constraints should be associated with each relationship. Let's apply our OCL constraint to the 'Writers 'books' relationship:

//This is the type that we are going to
//be binding the constraint to. The 
//constraint will only apply to writers.
EClass sourceType = w1.eClass();
		
//This is the feature (relationship) that
//we will be binding the constraint to. Adding
//this constraint will cause the knowledge
//base to only return books with from the
//same category as the Writer's existing books.
EStructuralFeature booksFeature = sourceType.getEStructuralFeature("books");
		
//Post the constraint to the knowledge
//base
kb.add(sourceType, booksFeature, con1);

After all of this initial setup is done, we can use GEMS EMF Intelligence to derive valid endpoints for the 'books' EStructuralFeature:

		
//Ask EMFIntelligence to derive the valid
//values for the feature. This should only
//return books f1 and f2.
List valid = kb.validTargets(w1, booksFeature);
		
//Check to make sure things worked
if(valid.size() == 2)
  System.out.println("It worked, the writer wrote "+((Book)valid.get(0)).getTitle()+" and"
                                                   +((Book)valid.get(1)).getTitle());
else
  System.out.println("Something went horribly wrong....");

The List (stored in the variable 'valid') contains all of the books in the knowledge base that meet the OCL constraint we specified.

Back to the top