Monday, April 29, 2013

How to create an EMF Profile

Whenever you want to store additional information to EMF-based models and you cannot or don't want to change the respective metamodel, EMF Profiles provide a convenient solution for extending metamodels in a non-intrusive and lightweight manner; comparable to how UML profiles allow to extend UML. For extending a metamodel, all you have to do is to create a profile, which can then be applied to models in order to store the additional information you want to add to the original model. In the following, we show how profiles are created step by step.

Extending the library metamodel

For illustrating the process of creating a profile, we extend the well-known library example metamodel. This metamodel basically contains three classes: the class Library, Writer, and Book.

Now assume, we need to add additional information to library models without having to change the metamodel and, thus, without the need to re-generate the model-, edit-, and editor code. In particular, we want to be able to store whether a book is an ebook and, if it is an ebook, in which format it is available (such as ePub or PDF). Additionally, we want to be able to annotate books with tags.

Creating a profile project

To create a new profile project, we start the dedicated wizard for profile projects by selecting File > New > Other and select EMF Profile > EMF Profile Project.


After clicking Next, we enter a name for the profile project, as well as additional information about the profile, such as its name and its namespace URI. For the name and the namespace URI, it is recommendable to apply the same naming conventions as for metamodels.


After hitting the Finish button, the wizard creates the EMF profile project and opens the created empty EMF profile diagram, which has been initialized with the information provided in the wizard already, as can be seen in the Properties view.

Modeling the profile

A profile consists of stereotypes, which extend EClasses of metamodels. In our scenario, we want to store additional information to instances of the class Book of the library metamodel. Thus, we will create stereotypes that extend the class Book. Therefore, we first have to import the class Book. To do that, we use the popup menu (right-click the canvas of the profile diagram editor). In the popup menu, we now select Import Metamodel Element... and choose the extlibrary metamodel and, in the next step, the EClass Book. As a result, we obtain a shortcut to Book in our profile diagram canvas.



Now, we can start creating stereotypes using the palette in the profile diagram editor. To store whether a book (i.e., an instance of the class Book) is an ebook, we create the stereotype EBook. As we want to apply this stereotype to instances of Book, we create an Extension relationship from the created stereotype to the imported class Book. Extension relationships have a multiplicity (e.g., 0..1, 0..*, 2..4, etc.). This multiplicity specifies how often a stereotype can be (and must be) applied within one profile application to an instance of the extended class (e.g., Book). In our scenario, the stereotype EBook should not be mandatory, since we might have books that are not ebooks and, thus, should not be annotated with the stereotype EBook. Thus, we use a lower-bound multiplicity of 0. Further, it wouldn't make any sense to apply the stereotype EBook multiple times to the same book. To prohibit multiple applications, we set the upper-bound multiplicity to 1.


Stereotypes may carry additional data. One way to allow for adding additional data is to add tagged values to stereotypes. Since we want to store the format of an ebook, we add the tagged value named format to the stereotype EBook. Tagged values are basically attributes and can have primitive Ecore types, such as EString, EBoolean, ect., as well as custom EEnum types. We want to store whether an EBook is available in the format of EPUB or PDF; thus, we create a new EEnum named EBookFormat with two literals, EPUB and PDF, and set the type of the attribute format to EBookFormat.

Side note: Although this isn't needed in our example, stereotypes may, in general, also contain cross references to existing model elements (in the base model or in the profile application), as well as containment references (i.e., the stereotype application owns additional model elements). For creating references, just use the palette in the diagram editor and set the properties of the added reference accordingly. You can also use inheritance among stereotypes, if needed.

As mentioned above, we also want to be able to annotate books with tags. Therefore, we add another stereotype named TaggedBook, which also extends the class Book, and add a tagged value named tags of type EString to the created stereotype. To enable multiple tags for one book, we may set tags to be multi-valued (i.e., an upper-bound of -1 in the properties of the tagged value) and/or set the multiplicity of the stereotype to be 0..*, which specifies that the stereotype TaggedBook may be applied arbitrarily often to one instance of a book.

Registered profiles

Having finished the profile, we may validate it and save it. If the profile is valid, it will be registered automatically to the local profile registry. You may inspect all currently registered profiles using the Registered EMF Profiles view, which can be added using Window > Show View > Other... > EMF Profiles > Registered EMF Profiles.


As can be seen in the screenshot above, the created profile has been registered correctly. Note that you can still modify your profile; it will be synchronized automatically with the local profile registry, as long as your profile is valid. If it is invalid, it will disappear from the registry until you fix the validation error.

Once your profile is available in the local registry you can apply it to models that conform to the extlibrary metamodel. This, however, will be covered in future posts... so make sure to stay tuned.