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

VIATRA/Integration/DeveloperDocumentation/Xcore

Aim of the project

The Xcore project aims to provide a textual syntax for the definition of EMF metamodels. You can use it not only to specify the structure of your model, but also the behavior of your operations and derived features as well as the conversion logic of your data types. It eliminates the dividing line between modeling and programming, combining the advantages of each.

Viewing the scope of the EMF-IncQuery project an idea may immediately arise; it would be really nice to use the powerful pattern language of EMF-IncQuery to define derived features in your Xcore metamodel. This projects aim to support exactly this functionality, that is, beyond the standard Xcore way to define derived features (basically with Xbase expressions), it is now possible to refer to pattern definitions in the Xcore files. One can specify which pattern should serve as the underlying logic for the evaluation of the given derived feature in runtime.

The integration was developed as seamlessly as possible; all the original Xcore semantics and toolset are still available, however, the IncQuery & Xcore editor now supports the definition of the above mentioned features with additional features like validation, proposal providers, etc.

Requirements

  1. Eclipse Kepler release
  2. Latest Xtext release (2.4.x)
  3. Xcore (you can download it from the Kepler update site for example). At the moment the latest build does not contain some required patches, so for the time being please download the Xcore source plugins from the EMF git repository http://git.eclipse.org/c/emf/org.eclipse.emf.git.
  4. EMF-IncQuery (you can download it for example from the Eclipse Marketplace)

Overview and example

You can get a really good overview about the Xcore project here: http://wiki.eclipse.org/Xcore. In this section we will use the same metamodel but with additional derived feature definitions. To start trying out the project, create a new Xcore project and an IncQuery & Xcore file with the file extension .xcoreiq.

Note that, at the moment you can only use the IncQuery support for Xcore files if the metamodel and the patterns are defined in the same project, that is, the project must have both Xcore and IncQuery natures.

The metamodel that we use deals with simple classes like Library and Books inside it. We also want to store the authors of these books and various properties like citations between the books, the own books of an author, etc.

Two kinds of derived features can be defined:

  • attributes (EAttribute) with the 'incquery-derived' keyword. Naturally, the type of these features can be only primitive types
  • references (EReference) with the 'incquery-derived refers' keyword. The type of these features can be any reference type (user-defined classes for example)

Metamodel (Library.xcoreiq)

class Library {  
	String name
	contains Writer[] authors opposite library
	contains Book[] books opposite library
}
class Writer {   
	String name 
	
	derived String lastName get {
		if (name != null) {
			val index = name.lastIndexOf(" ")
			if (index == -1) {
				name
			}
			else {
				name.substring(index+1)
			}
		}
	}
	
	container Library library opposite authors
	refers Book[] books opposite authors
	incquery-derived refers Book[] ownBooks spec ownBooksOfWriter
} 

class Book {
	String title  
	Integer pages
	BookCategory bookCategory
	refers Book[] citations
	refers Writer[] authors opposite books
	container Library library opposite books

	incquery-derived Integer numberOfCitations spec numberOfCitations 
	incquery-derived refers Book[] allCitations spec allBookCitations 
	incquery-derived Integer numberOfAuthors spec numberOfAuthors
}

enum BookCategory {
	Mystery = 0,
	ScienceFiction = 1,
	Biography = 2
}

Here we have defined 3 classes and the book category which is an enumeration for specifying the type of a book. Note the IncQuery based derived feature definitions. The formal definitions of these features:

  • Writer.ownBooks: the feature should return only those Books that have the Writer as the only author (no co-authors for the given book)
  • Book.allCitations: the feature should return all citations for the given book. This will be computed transitively, that is, if the citations are B1 -> B2 and B2 -> B3 then the set of all citations for the B1 book will contain both B2 and B3.
  • Book.numberOfCitations: the size of the Book.allCitations feature's value (the number of all citations)
  • Book.numberOfAuthors: the number of the co-authors for the given book

Pattern definitions (LibraryPatterns.eiq)

pattern ownBooksOfWriter(W : Writer, B : Book) {
	Writer.books(W, B);
	find numberOfAuthors(B, N);
	N == 1;
} 
pattern allBookCitations(B1 : Book, B2 : Book) {
	find bookCitation+(B1, B2);
}

pattern bookCitation(B1 : Book, B2 : Book) {
	Book.citations(B1, B2);
}

pattern numberOfCitations(B1 : Book, N) {
	N == count find allBookCitations(B1, _B2);
}

pattern numberOfBooksOfWriter(W : Writer, N) {
	N == count find bookOfWriter(W, _B);
}

pattern numberOfAuthors(B : Book, N) {
	N == count find writerOfBook(B, _W);
}

pattern writerOfBook(B : Book, W : Writer) {
	Book.authors(B, W);
}

pattern bookOfWriter(W : Writer, B : Book) {
	Writer.books(W, B);
}

Referring to the generated EPackage in the eiq file

An interesting problem arises when we want to develop the xcore and eiq files in parallel: in the metamodel we would like to specify derived features which would use pattern definitions which rely on the metamodel elements. To overcome this cyclic dependency problem, the eiq file editor uses the Xtext index and scoping when proposing EPackage imports. During the editing of the xcoreiq file, the corresponding EPackage is generated in the runtime, but the appropriate entry will only be inserted into the plugin.xml file if the xcoreiq file is error-free.

Generated Artifacts

The generated metamodel artifacts can be used in two different use cases:

  1. Dynamic Instance Mode: debugging of metamodels and queries are made easy with this functionality. One can develop the metamodel and queries at the same time, in the same workspace. You just need to create a dynamic instance model and you can modify your model on the fly. All the values of the features can be observed through the Properties View of Eclipse.
  2. Using the Generated Code: the standard EMF model/edit/editor/tests code can be also generated and used in an other instance of Eclipse.


Advanced issues

SettingDelegates for the evalutation of derived features


Back to the top