Defining a metamodel with UML

Supported Elements

Here are the UML elements you can use to define the metamodel :

The model we will define looks like this in UML :

Library UML model

The UML element name must be valid Java identifier. For example it can't contain whitespaces.

Package

Packages will help to organize your classes. Packages are not important for the needs of the Metamodel Generator, since a class name must be unique in the metamodel (see the Class section). They will only be useful when exporting the model using the XMI 1.0 standard, since package names are included in XMI 1.0 tags. Note they are no longer used in more recent XMI versions (1.1 to 2.1).

Note: the Metamodel Generator flattens UML packages into a single Ecore package, and gives this package the name of the metamodel.

Class

A UML Class is used to denote a concept (metatype) in your metamodel. We'll start by assuming we have a trivial, one-class model like this:

One-class model: Book with title : String and pages : int

The model shows a single class called Book with two attributes: title of type String and pages of type int.

A class name must be unique within the entire model. Two classes cannot share the same name, even in they are part of two different packages (because the Metamodel Generator flattens UML packages into a single package).

Abstract Class

According to your UML case tool, abstract classes can be represented using the <<abstract>> stereotype or setting to true the isAbstract attribute of the UML class. In a well-formed model, an abstract class should have subclasses.

Attribute

An attribute name must be unique within its class hierarchy (a super class must not define the same attribute name). An attribute name must be unique regarding its class roles (an attribute can't have the same name as a role of its class, or one of its super class). An attribute should specify its type (otherwise it will be considered as a String attribute). The type may be a primitive type or a class in the metamodel. If the type is a UML Class, this attribute becomes a composite relation.

Primitive type attributes

The type of attribute can be a primitive type. Here is the list of the supported primitive types, with the corresponding Java type :

Metamodel Data TypeJava Type
string java.lang.String
boolean, bool boolean
char char
integer, int int
short short
long long
float, real float
double double

Primitive types name are not case sensitive. "String", "string" and "STRING" are handled the same way.

Data type attributes

All the metatypes defined in a metamodel (for example, Book, Writer) implicitly derive from the EMF base class EObject. However, all the classes that a model uses are not necessarily EObjects. For example, assume we want to add an attribute of type java.util.Date to our metamodel. Before we can do so, we need to define an EMF DataType to represent the external type.

Data type definition: datatype JavaDate is of javaclass java.util.Date

As shown, a data type is simply a named element in the model that acts as a proxy for some Java class. The actual Java class is provided as an attribute with the <<javaclass>> stereotype, whose name is the fully qualified class being represented. With this data type defined, we can now declare attributes of type java.util.Date like this:

Attribute with data type as attribute type: Book has a publicationDate of type JavaDate

Note: Depending on your UML case tool, you can use a class with the <<datatype>> stereotype or the native UML DataType for this purpose.

EMF provides predefined standard datatypes that can be used in your UML models:

Ecore Data TypeJava Primitive Type or Class
EBooleanboolean
EBytebyte
ECharchar
EDoubledouble
EFloatfloat
EIntint
ELonglong
EShortshort
EBooleanObjectjava.lang.Boolean
EByteObjectjava.lang.Byte
ECharacterObjectjava.lang.Character
EDoubleObjectjava.lang.Double
EFloatObjectjava.lang.Float
EIntegerObjectjava.lang.Integer
ELongObjectjava.lang.Long
EShortObjectjava.lang.Short
EStringjava.lang.String
EJavaObjectjava.lang.Object
EJavaClassjava.lang.Class

Enumeration attributes

So far, we've looked at how to handle simple attributes. Another commonly used type of attribute is an enumeration. Enumeration-type attributes are implemented using the Java typesafe enum pattern.

Enumeration attribute and definition: Book has a category of class BookCategory, which is an enumeration of Mystery, ScienceFiction, and Biography

Note: According to your UML case tool, you can use a class with the <<enumeration>> stereotype or native UML Enumeration for this purpose.

Associations

All navigable roles in the model must be named in the metamodel. A role name must be unique within its class hierarchy (a super class must not define the same role name). A role name must be unique regarding its connected class attributes (a role can't have the same name as an attribute of its connected class, or one of its super class) A role should define a multiplicity (otherwise it will be considered as multiplicity "*").

One-way references

Let's expand our example model with another class Writer that has an association with class Book:

One-way reference: Book has a single author of class Writer, which contains a name : String

The association between a book and its writer is, in this example, a single one-way reference. The reference (role) name used to access the Writer from a Book is author.

Two-way references

A reference between objects can be bi-directional as well.

Two-way reference: an author may have written 0 or more books, but a book can only have one author

The association is now two-way, as indicated by the lack of an arrowhead on the Writer end of the association line. The role name used to access Books from a Writer is books.

Multiplicity-many references

You may have noticed in our example that the books association (from Writer to Book) is of multiplicity many (that is, 0..*). In other words, one writer may have written many books.

Containment references

Let's add a new class, Library, which will act as the container for Books.

Containment reference: a Library contains 0 or more books

In full, the association indicates that a Library is composed of 0 or more Books.

A role has an aggregation property, which can be "none", "aggregate" or composite". A role "aggregate" is considered in the same way as a role "none". The "composite" (also named containment or by-value aggregation) reference is indicated by the black diamond on the Library end of the association. Containment associations are particularly important because they identify the parent or owner of a target instance, which implies the physical location of the object when persisted. Indeed, a "composite" role has a different behavior when writing an XMI file. Any element contained by a "composite" role will be exported in an XMI file as a child element of the container, while an element attached by an "aggregate" or "none" role will be exported as a reference to another XML element (using an XMI identifier).

Inheritance

Let's say we want to create a subclass, SchoolBook, of our Book class.

Single inheritance: a SchoolBook is a kind of Book

In this case we used a Generalization from SchoolBook to Book to represent the inheritance relationship.

Multiple Inheritance

Consider the following example:

Multiple inheritance: a SchoolBook is a kind of Book and a kind of Asset (has a value : float)

Here we've made SchoolBook derive from two classes: Book and Asset. A class can have as many superclasses as necessary.

Related tasks
Importing a metamodel