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>