| Skip to content. |
Lehrstuhl Systemanalyse |
| Language Modelling HomeA MOF 2.0 for JavaTextual Editing FrameworkModel Pattern | |
This tutorial is a step by step introduction. We will use a simple meta-model and show how to create a repository from the meta-model, how to extent the generated repository with own code, and finally how to create an instance of that meta-model, create some model entities, and demonstrate how accessing and updating of model properties work. The sources for this tutorial are also part of the test environment for the source distribution; they are available in aMOF2.0forJava.jar/test.
Before we begin make sure that you have installed at least a version 5.0 JDK. First create a new empty project folder, download aMOF2.0forJava.jar from the download section and place it into the new folder.
Consider that you need to implement a store keeping system for a little warehouse. You will need a data-model to store the state of the warehouse, and you decide to use MOF as a middle ware for that task. The image below shows a meta-model that describes a warehouse:

We need this model in a format that A MOF 2.0 for Java can understand, and this is the XMI (Xml Model Interchange) format. Download warehouse-meta.xml and place it in our folder. Currently A MOF 2.0 for Java does only understand XMI version 2.0 with MOF written in the CMOF model.
We can use a special A MOF2 - Eclipse Plugin to look a little closer at our meta-model. It does not only allow us to examine our specific warehouse meta-model, but also any model (e.g. CMOF) that is provided as an XMI file. The following section describes how to install the plugin and how to load the warehouse.
You can download the Eclipse-Plugin from A MOF 2 at berliOS. When you are finished, close Eclipse, install the plugin and rerun Eclipse. Open the model view: Select open view from the windows menu and select MOF2Plugin / Model View. We will use this view to navigate trough models. Now open the view Basic / Properties in the same way. The property view shows the properties and values of the model elements. Add a new repository to the view by using the create button on the upper right side of the view and choose local repository from the new window. As a default the CMOF model is loaded into the view. Let us load the warehouse meta-model; right-click the top-level element Repository and choos Add model .... Select load xmi file and browse for warehouse-meta.xml. Now we can navigate trough the warehouse meta-model and view the properties of each element as specified in the XMI file.
Below you can see a screenshot of the A MOF2 - Eclipse Plugin where the warehouse meta-model was loaded into the Model View.

Let us analyse the warehouse by both looking at the model's image at the top and using the Eclipse Plugin.
There are Racks that can contain Boxes and boxes that can contain Items. The Contains relation is modeled abstract between the abstract classes Container and Element. To convince yourself, navigate to the Contains relation in the Eclipse Model View and then search for isAbstract in the Properties View. Each Element (Rack, Box, or Item) has an id, and a position that will be derived from ids. Racks and Boxes are Container and thus can contain Elements; but a Rack only contains Boxes, and Boxes only Items. Items have a weight and Boxes have a weight that is the sum of all weights of all contained Items.
Hint (Eclipse Plugin):
You can view all inherited features of a meta-class by right-clicking the appropriate class (e.g. Item) and selecting Show all inherited features.
Now we can start on programming with A MOF 2.0 for Java. Create a sub folder src. Now we are going to create a little program that generates a repository from the warehouse meta-model. You can download the complete source-file, put it to the src directory.
import hub.sam.mof.Repository;
import cmof.reflection.*;
import cmof.Package;
A few imports needed.
public class GenerateRepository {
public static void main(String[] args) throws Exception {
Repository repository = Repository.getLocalRepository();
System.out.println("Generate repository");
The class Repository provides our MOF's main interface. It offers methods to create meta-models and models, to load and write XMI files, or to generate repository code.
Extent cmofExtent = repository.getExtent(Repository.CMOF_EXTENT_NAME);
Package cmofPackage = (Package)cmofExtent.query("Package:cmof");
Extents are livings spaces for model elements. Usually you want to have an extent for each model. Repository provides a build in extent with the name CMOF_EXTENT_NAME. This extent contains the CMOF model, the M3-model, the modelling for meta-models. The next line extracts the CMOF package, the main package of the CMOF-model from this extent. This package contains all CMOF concepts, like classes, attributes, associations, data type, etc.
Extent warehouseMetaExtent = repository.createExtent("warehouseMetaExtent");
repository.loadXmiIntoExtent(warehouseMetaExtent, cmofPackage, "warehouse-meta.xml");
Now we create a new extent based on this meta-meta package. This new extent can now inhabit instances of all concepts in the CMOF package. Into this extent we load our warehouse meta-model from the XMI-file. After that warehouseMetaExtent will contain all the elements defined in the meta-model as instances of CMOF elements.
repository.generateCode(warehouseMetaExtent, "src/");
}
}
Finally we generate the code for a repository based on the meta-data stored in warehouseMetaExtent. This code will be placed in the src directory.
Now you can compile and run this application. On a unix machine this can be done with:
javac -classpath aMOF2.0forJava.jar src/GenerateRepository.java
java -classpath aMOF2.0forJava.jar:src GenerateRepository
We already did the automatic generation of the repository. But in our meta-model are two derived features, for that you, the user, have to provide the code. In case you don't provide code for derived features or operations, an exception will be raised when those features are accessed. Before we create custom code for the features Element::position and Box:weight, we should take a look at the generated classes.
The given meta-model was packed in a CMOF package (look at the XMI to convince yourself). For this CMOF package warehouse a Java package with same name was generated. It includes all the repository Java files; these are: A interface for each meta-class with same name (the proxy interfaces), a class for each meta-class with meta-name + "Dlg" as name (the proxy delegators), and a class for each meta-class with meta-name + "Impl" as name (the proxy implementations). For example for meta-class Box these are: interface Box, class BoxDlg and class BoxImpl.
Background: Every meta object (like Box) can be accessed trough an untyped reflection API. The generated Java interfaces and classes in the AMOF repository have the function of a typed wrapper for these meta objects. They add information so that accessing (e.g.) a Box is more type-safe.
Finally the repostiory generated a warehouseFactory for us which we will use to instantiate meta classes from the warehouse meta-model later.
The proxy interfaces contain getter and setter methods for all structural features, like attributes or navigable association ends and normal methods for operations. Structural features with higher multiplicity only have getter methods that return sets, which can be manipulated in order to change the values of the feature. The proxy implementations implement those interfaces; but you do not care about them, because you use the generated factory to create proxy objects. The delegator proxies are for you to extend in order to define custom code to the repository.
This means that, in order to provide code for Element::position and Box:weight, we have to extent ElementDlg and BoxDlg. In order to be found by the repository those extensions must be called ElementCustom and BoxCustom and must be placed in the same package as the delegators. You should now download ElementCustom.java and BoxCustom.java and place them in src/warehouse.
package warehouse;
public class ElementCustom extends ElementDlg {
We import some classes and declare ElementCustom as specialization to ElementDlg
public String getPosition() {
Container container = getContainer();
if (container != null) {
return container.getPosition() + "." + getIdentifier();
} else {
return getIdentifier();
}
}
}
Here we give the custom implementation for accessing the feature container, a association end that is navigable from Element. You see that we use features of Element via this (getContainer, getIdentifier). This implementation simply constructs a String from the name of this Element and the names from it container, and the container of that container and so one. Please note the when a feature is not set, the according getter will return the null value. We utilized this in abortion constraint container!=null. This is all that is needed to provide custom code for Element. We do the same for Box::weight but of course with a different implementation:
public int getWeight() {
int weight = 0;
for (Item item: getItem()) {
weight += item.getWeight();
}
return weight;
}
Here we sum over all items in a box. The for-loop demonstrate how to use the values of properties with higher multiplicity.
Our warehouse repository is finished. We will now write a little application that demonstrates how to use the repository, and that will test our custom implementations. You can download the complete code of UseRepository.java:
import hub.sam.mof.Repository;
import cmof.Package;
import cmof.reflection.Extent;
import warehouse.*;
public class UseRepository {
public static void main(String[] args) throws Exception {
Repository repository = Repository.getLocalRepository();
Extent cmofExtent = repository.getExtent(Repository.CMOF_EXTENT_NAME);
Package cmofPackage = (Package)cmofExtent.query("Package:cmof");
Extent warehouseMetaExtent = repository.createExtent("warehouseMetaExtent");
repository.loadXmiIntoExtent(warehouseMetaExtent, cmofPackage, "warehouse-meta.xml");
Package warehousePackage = (Package)warehouseMetaExtent.query("Package:warehouse");
Extent warehouseExtent = repository.createExtent("warehouseExtent");
This are all things we have already done in the generation application. Note that this time, we imported the generated warehouse Java package. Summary: We locate the CMOF package, create a extent from it, load our warehouse meta-model into that new extent, then locate the warehouse package in the uploaded content, created a new extent for the warehouse package. Now we have a extent called warehouseExtent that we can use to store warehouse data.
warehouseFactory factory = (warehouseFactory)repository.createFactory(warehouseExtent,
warehousePackage);
This will create a factory instance for the warehouse. This warehouseFactory contains methods to create instances for all warehouse meta-classes. The factory will place all created instances in the warehouseExtent. Now we will create some warehouse entities:
Rack a = factory.createRack(); a.setIdentifier("a");
Rack b = factory.createRack(); b.setIdentifier("b");
Box a1 = factory.createBox(); a1.setIdentifier("a1");
Box a2 = factory.createBox(); a2.setIdentifier("a2");
Box b1 = factory.createBox(); b1.setIdentifier("b1");
a.getBox().add(a1); a.getBox().add(a2);
b.getBox().add(b1);
Item a1A = factory.createItem(); a1A.setIdentifier("a1A"); a1A.setWeight(1);
Item a2A = factory.createItem(); a2A.setIdentifier("a2A"); a2A.setWeight(2);
Item a2B = factory.createItem(); a2B.setIdentifier("a2B"); a2B.setWeight(3);
Item b1A = factory.createItem(); b1A.setIdentifier("b1A"); b1A.setWeight(1);
a1.getItem().add(a1A);
a2.getItem().add(a2A); a2.getItem().add(a2B);
b1.getItem().add(b1A);
System.out.println("Contents of a2: " + a2.getContent().size());
System.out.println("Container of a2B: " + a2B.getContainer().getIdentifier());
System.out.println("Position of a2B: " + a2B.getPosition()); // a.a2.a2B
System.out.println("Weight of a2: " + a2.getWeight()); // 2+3=5
}
}
Below you can see how the model of the code above looks like.

This isn't new; we have already seen how to access a objects properties in the custom code section. We will discuss it some more when we analyze the output of this program, but we need to compile it and to run first.
javac -classpath aMOF2.0forJava.jar `find src -name="*.java"`
java -classpath aMOF2.0forJava.jar:src UseRepository
The output should read something like:
Contents of a2: 2
Container of a2B: a2
Position of a2B: a.a2.a2B
Weight of a2: 5
The Element a2 is a box, and we added two items a2A and a2B to this box, using the item property. Since item does subset content, adding things to item caused the repository to also add those items to content. The property content depends on item, since item subsets content.
A similar thing happened to the container of a2B. We never set this property directly, but content and container are related through the association contains. Thus, when we set a2B to be a content of a2, the repository automatically set a2 to be the container of a2B.
The third and forth line demonstrate our custom implementations. Position is a concatination of a2B's container identifiers, and the weight of a2 is a sum of the weights of its items.
There is another way on how we can use a meta-model to create model entities. Instead of always creating a cmof extent and loading the meta-model into this extent we can also save all this information as a static java file (e.g. WarehouseModel.java) and use it to create the meta-extent (e.g. warehouseMetaExtent).
Below you can see which modifications have to be applied to GenerateRepository.java and UseRepository.java.
import hub.sam.mof.Repository;
import cmof.reflection.*;
import cmof.Package;
public class GenerateRepository {
public static void main(String[] args) throws Exception {
Repository repository = Repository.getLocalRepository();
System.out.println("Generate repository");
Extent cmofExtent = repository.getExtent(Repository.CMOF_EXTENT_NAME);
Package cmofPackage = (Package)cmofExtent.query("Package:cmof");
Extent warehouseMetaExtent = repository.createExtent("warehouseMetaExtent");
repository.loadXmiIntoExtent(warehouseMetaExtent, cmofPackage, "warehouse-meta.xml");
repository.generateCode(warehouseMetaExtent, "src/");
repository.generateStaticModel(warehouseMetaExtent, "warehouse.WarehouseModel", "src/");
Here we call generateStaticModel(...) to create the static model in WarehouseModel.java.
}
}
import hub.sam.mof.Repository;
import cmof.Package;
import cmof.reflection.Extent;
import warehouse.*;
public class UseRepository {
public static void main(String[] args) throws Exception {
Repository repository = Repository.getLocalRepository();
Extent warehouseMetaExtent = WarehouseModel.create();
Package warehousePackage = (Package)warehouseMetaExtent.query("Package:warehouse");
Extent warehouseExtent = repository.createExtent("warehouseExtent");
... } }