The UML2 project provides an EMF based implementation of the UML 2.x metamodel in Java. It is used by open source model driven development tools such as openArchitectureWare and commercial modeling tools like IBM Rational Software Architect.
The fact that the underlying technology is the Eclipse Modeling Framework (EMF) makes it possible to use the EMFBuilder with the UML2 metamodel.
The article Getting Started with UML2 by Kenn Hussey explains how to create UML2 models with the Eclipse editor and how to create them programmatically with Java code.
The data model is shown in the following diagram.
In the following it is shown how to create (parts of) this model with the EMFBuilder. Compare the code below to the original code in the article!
We use the UMLFactory for the EMFBuilder.
def builder = new EMFBuilder(UMLFactory)
We create a Model as the root node and then we create four primitive types and store
them in Groovy variables because we have to reference them later on.
def epo2Model = builder.Model(name: 'epo2') {
packagedElement {
def intPrimitiveType = PrimitiveType(name: 'int')
def stringPrimitiveType = PrimitiveType(name: 'String')
def datePrimitiveType = PrimitiveType(name: 'Date')
def skuPrimitiveType = PrimitiveType(name: 'SKU')
We define an enumeration OrderStatus with three literals.
def orderStatusEnumeration = Enumeration(name: 'OrderStatus') {
ownedLiteral {
EnumerationLiteral(name: 'Pending')
EnumerationLiteral(name: 'Back Order')
EnumerationLiteral(name: 'Complete')
}
}
The following code snippet shows the definition of the class Address.
All the attributes are defined as a Property.
Here the primitive type stringPrimitiveType defined above is used.
def addressClass = Class(name: 'Address' ,isAbstract: true) {
ownedAttribute {
Property(name: 'name', type: stringPrimitiveType, lower: 0, upper: 1)
Property(name: 'country', type: stringPrimitiveType, lower: 0, upper: 1)
}
}
In UML2 there is the concept of "generalization" to model inheritance relationships. The class
USAddress is a subclass of Address. This is expressed by using
the Generalization object.
def usAddressClass = Class(name: 'USAddress') {
generalization {
Generalization(general: addressClass)
}
ownedAttribute {
Property(name: 'street', type: stringPrimitiveType, lower: 0, upper: 1)
Property(name: 'city', type: stringPrimitiveType, lower: 0, upper: 1)
Property(name: 'state', type: stringPrimitiveType, lower: 0, upper: 1)
Property(name: 'zip', type: intPrimitiveType, lower: 0, upper: 1)
}
}
An association is a relationship between two types. For each end of an association the type, the navigability, the aggregation, the name and the lower and upper bound have to be specified. The UML2 API method Type.createAssociation(). can be used to create an association and to connect the ends to the respective types.
The following code snippet creates the composite association between Supplier
and Purchase (see the edge with the black diamond from from Supplier
to Purchase) with the name orders.
supplierClass.createAssociation(
true, AggregationKind.COMPOSITE_LITERAL,
"orders", 0, LiteralUnlimitedNatural.UNLIMITED,
purchaseOrderClass, false, AggregationKind.NONE_LITERAL,
"", 1, 1)
The one to many association between Customer and PurchaseOrder is created
with the following code snippet.
customerClass.createAssociation(
true, AggregationKind.NONE_LITERAL,
"orders", 0, LiteralUnlimitedNatural.UNLIMITED,
purchaseOrderClass, true, AggregationKind.NONE_LITERAL,
"customer", 1, 1)
Finally the model is saved into a file.
UML2Utilities.save('data/epo2.uml', epo2Model)
The full source code is available in the EMFBuilder distribution.
In the article Introduction to UML2 Profiles Ken Hussey explains how to create an UML2 profile with the Eclipse editor and programmatically with Java and and how to apply this profile to an UML2 model.
... work in progress ...
There are the following things to point out.
The source code is available with the EMFBuilder distribution.
Thanks to László Sütő for contributing a patch.