Medea provides a template to generate Java classes from a UML class diagram. This is perhaps the most comprehensive template that handles most of the elements of a class diagram. It can serve as a blueprint for other, simplier templates that produce value objects, entity beans etc.
Consider this fictional class diagram.
It contains all artifacts the template handles:
Since there's only one template in this target, it can be either applied directly or by ant target trans_java:
C:\projects\javaclass>ant trans_java Buildfile: build.xml trans_java: trans: [echo] Java [java] /projects/javaclass/gen/data/geom/plain/Point.java [java] /projects/javaclass/gen/data/graph/Shape.java [java] /projects/javaclass/gen/data/graph/TextArea.java [java] /projects/javaclass/gen/data/graph/Drawable.java [java] /projects/javaclass/gen/data/graph/Refreshable.java [java] /projects/javaclass/gen/data/graph/Resizable.java [java] /projects/javaclass/gen/data/Alignment.java [java] Creates Java classes and interfaces for all classes. BUILD SUCCESSFUL Total time: 3 seconds
These files are produced from this example diagram:
Let's examine major elements of 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>
<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 }
<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>
<!-- associations --> <xsl:for-each select="$ends"> <xsl:variable name="myEnd" select="current()"/> <xsl:variable name="otherEnd" select="cr:otherEnd(current(), root(.))"/> <xsl:variable name="myUpper" select="cr:multiUpper($myEnd)"/> <xsl:variable name="otherUpper" select="cr:multiUpper($otherEnd)"/> <xsl:variable name="myClassName" select="cr:endClassName($myEnd, root(.))"/> <xsl:variable name="otherClassName" select="cr:endClassName($otherEnd, root(.))"/> <xsl:variable name="myFieldName" select="cr:endFieldName($myEnd, root(.))"/> <xsl:variable name="otherFieldName" select="cr:endFieldName($otherEnd, root(.))"/> <xsl:variable name="myFieldNameUpper" select="cr:upper($myFieldName)"/> <xsl:variable name="otherFieldNameUpper" select="cr:upper($otherFieldName)"/> /** xmi.id=<xsl:value-of select="@xmi.id"/> * myUpper=<xsl:value-of select="$myUpper"/> otherUpper=<xsl:value-of select="$otherUpper"/> * @unmodifiable */<xsl:choose> <xsl:when test="$myUpper = -1 and $otherUpper = 1"> Set <xsl:value-of select="$myFieldName"/>Set; /** * @unmodifiable */ Set get<xsl:value-of select="$myFieldNameUpper"/>Set() { <xsl:value-of select="$myFieldName"/>Set; } /** * @unmodifiable */ void set<xsl:value-of select="$myFieldNameUpper"/>Set(Set <xsl:value-of select="$myFieldName"/>Set) { .<xsl:value-of select="$myFieldName"/>Set = <xsl:value-of select="$myFieldName"/>Set; } /** * @unmodifiable */ void add<xsl:value-of select="$myFieldNameUpper"/>(<xsl:value-of select="concat($myClassName, ' ', $myFieldName)"/>) { <xsl:value-of select="$myFieldName"/>Set.add(<xsl:value-of select="$myFieldName"/>);<!-- <xsl:if test="$otherEnd/@isNavigable = 'true'"> (<xsl:value-of select="$myFieldName"/> != null) <xsl:value-of select="concat($myFieldName, '.set', $otherFieldNameUpper, '(this')"/>); </xsl:if>--> } </xsl:when>
<!-- operations --> <xsl:for-each select="cr:operations(current())"> <xsl:variable name="visibility" select="cr:visibility(current())"/> <xsl:variable name="returnType" select="cr:returnType(current(), root(.))"/> <xsl:variable name="abstract" select="cr:abstract(current())"/> <xsl:variable name="static" select="cr:static(current())"/> <xsl:variable name="params" select="cr:parameters(current(), root(.))"/> /** * <![CDATA[<!-- begin-user-doc --> * <!-- end-user-doc --> * @generated]]> */ <xsl:value-of select="concat($visibility, ' ', $abstract, ' ', $static, ' ', $returnType, ' ', @name)"/>(<xsl:for-each select="$params"><xsl:value-of select="concat(cr:dataType(current(), root(.)), ' ', @name)"/><xsl:if test="position() != last()">, </xsl:if></xsl:for-each>)<xsl:choose> <xsl:when test="$abstract">; </xsl:when> <xsl:otherwise> { // begin-user-code <xsl:if test="$returnType != 'void'"> <xsl:value-of select="$returnType"/> ret = null; return ret;</xsl:if> // end-user-code } </xsl:otherwise></xsl:choose> </xsl:for-each>
<!-- interfaces --> <xsl:for-each select="cr:interfaces(root(.))"> <xsl:variable name="className" select="cr:nameUpper(current())"/> <xsl:variable name="visibility" select="cr:visibility(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:result-document href="{$fileName}"> package <xsl:value-of select="$package"/>; import 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"/> * <![CDATA[<!-- begin-user-doc --> * <!-- end-user-doc --> * @generated]]> */ <xsl:value-of select="$visibility"/> interface <xsl:value-of select="$className"/><xsl:value-of select="$extends"/> { <xsl:for-each select="cr:operations(current())"> <xsl:variable name="visibility" select="cr:visibility(current())"/> <xsl:variable name="returnType" select="cr:returnType(current(), root(.))"/> <xsl:variable name="params" select="cr:parameters(current(), root(.))"/> /** * @unmodifiable */ <xsl:value-of select="concat($visibility, ' ', $returnType, ' ', @name)"/>(<xsl:for-each select="$params"><xsl:value-of select="concat(cr:dataType(current(), root(.)), ' ', @name)"/><xsl:if test="position() != last()">, </xsl:if></xsl:for-each>); </xsl:for-each> } </xsl:result-document> </xsl:for-each>
<!-- enumerations --> <xsl:for-each select="cr:enumerations(root(.))"> <xsl:variable name="className" select="cr:nameUpper(current())"/> <xsl:variable name="attrs" select="cr:enumerationLiterals(current())"/> <xsl:variable name="visibility" select="cr:visibility(current())"/> <xsl:variable name="package" select="cr:classPackage($purePackage, current(), root(.))"/> <xsl:variable name="fileName" select="cr:fileNameJava($purePackage, $className, current(), root(.))"/> <xsl:result-document href="{$fileName}"> package <xsl:value-of select="$package"/>; /** fileName=<xsl:value-of select="$fileName"/> * <![CDATA[<!-- begin-user-doc --> * <!-- end-user-doc --> * @generated]]> */ <xsl:value-of select="$visibility"/> class <xsl:value-of select="$className"/> { private String label; /** * <![CDATA[<!-- begin-user-doc --> * private constructor for enum static members * <!-- end-user-doc -->' * @generated]]> */ private <xsl:value-of select="$className"/>(String label) { this.label = label; } <xsl:for-each select="$attrs"> /** * @unmodified */ public static final <xsl:value-of select="concat($className, ' ', @name)"/> = new <xsl:value-of select="$className"/>("<xsl:value-of select="@name"/>"); </xsl:for-each>