Quick Start

The following example is very simplistic but will take you through the important stages. We will model two entities with a relationship between them and will generate and examine Java classes. We assume the user's knowledge of UML and basic tools like ant.

Design entities

Let's model two entities, Customer and PurchaseOrder, with one-to-many relationship:

Modelling in MagicDraw 11.5

Modelling in MagicDraw 11.5

Modelling in Rational Rose

Modelling in Poseidon for UML CE 6.0

Export into XMI

Save the resulting XMI file into the chosen project directory. While exporting in XMI format is easy in Poseidon and MagicDraw, Rational Rose will require a plug-in.

Saving as XMI 2.1 in MagicDraw 11.5

Saving as XMI 2.1 in MagicDraw 11.5

Saving as XMI 1.1 in Rational Rose with Unisys UML Export plugin

Saving as XMI 1.2 in Poseidon for UML CE 6.0

Set up project properties

You'll need to choose a name for your project, project's base packages and a directory where it will reside. You can either set them up as parameters in build.properties file or provide later as external parameters during transformation.

Edit build.properties file in Medea's resources directory: res.

projectName=quickstart
modelFile=c:/projects/medea/model/quickstart.xml

# directory where the generated project will reside
projectDir=/projects/quickstart

# package name that will be prepended to all packages in the model, like 'com.mycompany'; set it to  void not to add  anything
basePackage=void

# name of the subpackage where all pure classes (not having any stereotype) will reside
purePackage=data

Transform

We'll apply a Java template that generates Java classes from all classes found in the model.

Stay in in the res directory. We'll execute an ant target from the build file there: build.xml.

  • Target trans executes Saxon transformer with the template set to Java.xsl. All other template parameters are passed from build.properties file.
C:\projects\medea\res>ant trans -Dtemplate=Java
Buildfile: build.xml

trans:
     [echo] Java
     [java] /projects/quickstart/gen/data/Customer.java
     [java] /projects/quickstart/gen/data/PurchaseOrder.java
     [java] Creates Java classes and interfaces for all classes not marked by a stereotype.

BUILD SUCCESSFUL
Total time: 2 seconds

Alternatively you can use the XSLT processor from the command line. In this case the template parameters must be passed as name-value pairs.

C:\projects\medea>java -jar %SAXON_HOME%\saxon8.jar model\quickstart.xml style\Java.xsl projectDir=/projects/quickstart basePackage=void purePackage=data projectName=quickstart
/projects/quickstart/gen/data/Customer.java
/projects/quickstart/gen/data/PurchaseOrder.java
Creates Java classes and interfaces for all classes not marked by a stereotype.

Note that the template prints out names of the files it generates as well as its short documentation.

Result

You will see two new files, in the project directory /projects/quickstart, directory for generated source files gen and package data.

/projects/quickstart/gen/data/Customer.java

/projects/quickstart/gen/data/PurchaseOrder.java

A closer look at the template

Let's take a closer look at how Java.xls template transforms our entities into source files.

Java.xsl

  • The template uses classes function to select all classes from the model regardless of their stereotype
  • The for-each statement iterates thru classes
    • We use functions to collect names, attributes, association ends etc. as well as construct the resulting filename (note how the parameter $purePackage is used)
    • Function results are saved in variables. We will use these variables throughout the template
      <xsl:for-each select="cr:classes('void', root(.))">
                      <xsl:variable name="className" select="cr:nameUpper(current())"/>
                      <xsl:variable name="ends" select="cr:ends(current(), root(.))"/>
                      <xsl:variable name="attrs" select="cr:attributes(current())"/>
                      <xsl:variable name="visibility" select="cr:visibility(current())"/>
                      <xsl:variable name="abstract" select="cr:abstract(current())"/>
                      <xsl:variable name="package" select="cr:classPackage($purePackage, current(), root(.))"/>
                      <xsl:variable name="fileName" select="cr:fileNameJava($purePackage, $className, current(), root(.))"/>
                      <xsl:variable name="extends">
                              <xsl:if test="cr:extends(current(), root(.)) != ''"> extends <xsl:value-of select="cr:extends(current(), root(.))"/></xsl:if>
                      </xsl:variable>         
                      <xsl:variable name="implements">
                              <xsl:choose>
                                      <xsl:when test="cr:implements(current(), root(.)) != ''"> implements  <xsl:value-of select="cr:implements(current(), root(.))"/></xsl:when>
                              </xsl:choose>
                      </xsl:variable>
      
  • This template code instructs to write to the resulting document, composes import statements, javadoc, class declaration and a default constructor (note how an empty HashSet is created when there's a many-to-one relationship)
    <xsl:result-document href="{$fileName}"><xsl:value-of select="$package"/>;
    java.util.*;
    <xsl:value-of select="cr:classImports($purePackage, 'void', root(.))"/>
    <xsl:value-of select="cr:classImports($purePackage, 'entity', root(.))"/>
    
    /** fileName=<xsl:value-of select="$fileName"/> xmi.id=<xsl:value-of select="@xmi.id"/>
    * <![CDATA[<!-- begin-user-doc -->
    * <!-- end-user-doc -->
    * @generated]]>
    */
    <xsl:value-of select="concat($visibility, ' ', $abstract)"/> class <xsl:value-of select="$className"/><xsl:value-of select="$extends"/><xsl:value-of select="$implements"/> {
            /**
            * <![CDATA[<!-- begin-user-doc -->
            * no argument constructor
            * <!-- end-user-doc -->
            * @generated]]>
            */
    <xsl:value-of select="$className"/>() {
                    <xsl:for-each select="$ends">
                            <xsl:if test="cr:multiUpper(current()) = -1">
                    <xsl:value-of select="cr:endFieldName(current(), root(.))"/>Set = new HashSet();
                    </xsl:if>
                    </xsl:for-each>
                    // begin-user-code
                    // end-user-code
            }
    
  • This template code iterates over class' attributes and creates their declarations, getters and setters
            <xsl:for-each select="$attrs">
            <xsl:variable name="name" select="cr:name(current())"/>
                    <xsl:variable name="nameUpper" select="cr:nameUpper(current())"/>
                    <xsl:variable name="dataType" select="cr:dataType(current(), root(.))"/>
                    <xsl:variable name="initialValue" select="cr:initialValue(current())"/>
            /** xmi.id=<xsl:value-of select="@xmi.id"/>
            * @unmodifiable
            */
    <xsl:value-of select="concat($dataType, ' ', $name)"/><xsl:if test="$initialValue != ''"> = <xsl:value-of select="$initialValue"/></xsl:if>;
            /** 
            * @unmodifiable
            */
    <xsl:value-of select="$dataType"/> get<xsl:value-of select="$nameUpper"/>() {
            <xsl:value-of select="$name"/>;
            }
            /** 
            * @unmodifiable
            */
    void set<xsl:value-of select="$nameUpper"/>(<xsl:value-of select="concat($dataType, ' ', $name)"/>) {
            .<xsl:value-of select="$name"/> = <xsl:value-of select="$name"/>;
            }
            </xsl:for-each>
    
  • Other template blocks will produce associations

We've covered basic steps of Medea transformations and you can now start using other templates to generate source code for application layers. You can also move on to more complex examples that use ant build targets to transform and build components and applications.