2. Advanced Code Generation

This chapter describes the code generation functions offered by Poseidon for UML and the options for customizing the code generation templates. Code generation based on standard templates is available in all editions of Poseidon for UML. The standard templates define code generation for Java and HTML. With the Developer and Professional Editions, you have the option of changing the code generation templates to suit your specific requirements. You can even create new templates to generate code for a different programming language such as C#.

2.1. Velocity Template Language

Code generation in Poseidon for UML is based on the Velocity Template Language. Velocity is an open source template engine developed as part of the Apache/Jakarta project. Originally designed for use in the development servlet based Web applications, it has also proved to be useful in other areas of application including code generation, text formatting and transformation.

The Velocity Template Language (VTL) supports two types of markup elements: references and directives. Both references and directives can be intermixed freely with the (non-VTL) content of a template, as shown in the examples below.

Since templates have been widely used in the field of Web page generation, we will begin with a simple HTML example. The second example demonstrates the use of VTL to generate Java code.

For further information on Velocity – including complete documentation of the Velocity Template Language – please go to the Velocity Web site at http://jakarta.apache.org/velocity/.

2.1.1. References

References are variable elements referring to some entity provided by the context. A reference such as $userName or $userList can be used to access and store a particular data structure for use within a template; thus, references establish the connection between a template and the context of the Velocity engine.

Within a template it is possible to create a new reference at any time and to assign a value to the new reference. This is done using the #set directive (see directives). This means you can add references to the active context as required. If a reference name is used within a template for which no corresponding object or value exists in the active context, the reference name is treated as plain text, i.e. it is output "as is" just like the other (non-VTL) elements of the template.

Every reference must have a unique name. The name (also known as the VTL identifier) begins with a dollar sign $ followed by a string of characters as described in the following table:

$dollar sign - the dollar sign must be the first character in the reference name, and it may not occur in any other position.
a-z, A-Zalphabetic characters - only standard characters are allowed, no accented or diacritical characters. The first character following the dollar sign must always be an alphabetic character.
0-9numerical characters
-minus sign (hyphen)
_underscore

A regular expression describing the reference name syntax would be:

$[a-zA-Z][a-zA-Z0-9_/-]*

In addition to referencing variables, it is also possible to specify attributes and methods by means of the VTL reference syntax. Using references such as $item.name and $item.price, you can dynamically insert the attributes associated with the specified object. Likewise, you can access the methods of a referenced object (for example a Java object) using a reference such as $item.getNameAsString(). This will return the result of applying the given method to the specified object.

Taking this one step further, you will find that the standard Java templates supplied with Poseidon for UML make extensive use of the following syntax:

#set ($name = $currentOp.getNameAsString())

Here the reference $name is dynamically set to the string returned by the method $currentOp.getNameAsString. This use of references to elements of the context establishes a very powerful connection between the templates and the template API.

2.1.2. Directives

Directives in VTL are a defined set of commands that can be used for basic control functions within a template. For example you can us the directives to create typical procedural branches (if/else) and loops (foreach).

The current set of VTL directives comprises the following commands:

#set()function for assigning a value to a reference
#if() #else#elseif()#endcommon conditional functions used for branching
#foreach()#endlooping function
#include() #parse()functions for including code from another template or static resource
#macro()#endfunction for defining a reusable set of commands

For complete information on the use of these directives please refer to the Velocity documentation (see http://jakarta.apache.org/velocity/).

2.1.3. Comments

Particularly in the case of templates used for code generation it may be advisable to use comments in the templates to explain their use. Comments can be added to a template by means of the following syntax:

## Single line comment ...The comment continues up to the end of the line. This
 is comparable to the syntax for single line comments in
 Java or C beginning with g.
#* Inline or multiline comment *#The comment continues up to the closing character *#.
 This is comparable to the syntax for inline and multiline
 comments in Java or C beginning with /* and ending with */.

The use of comments in VTL is illustrated by the examples below.

2.1.4. Examples

Example 14.1. Simple HTML Template

This example uses VTL markup intermixed with HTML code to generate dynamic Web pages based on information retrieved from the context (e.g. from a database).

 #* This is an example of a simple VTL template
    for generating dynamic HTML pages. *#

                                <HTML>
                                <HEAD>
                                <TITLE>Holiday Weekend</TITLE>
                                </HEAD>

                                <BODY>
                                <B>$roomList.size() rooms available
      at special holiday weekend rates! </B>
                                <BR>Check in for a luxurious holiday
      weekend at these amazing prices.
                                <BR> Choose from: #set( $count = 1 )

                                <TABLE> #foreach( $room in $roomList )
                                <TR>
                                <TD>$count)</TD>
                                <TD>$room.type</TD>
                                <TD>$room.price</TD>
                                </TR> #set( $count = $count + 1 ) #end
                                </TABLE>

                                <BR> Call today for a reservation.
      Toll free number: $freePhone
                                </BODY>
                                </HTML> 

This example makes use of VTL references and directives to generate an HTML page based on data from an external data source, for example a database. The data source is referenced by means of the elements $roomList and $room (with its attributes $room.type and $room.price). When this template is applied, the directives and references are interpreted and the results are inserted into the generated HTML code.

The resulting HTML page might look something like this:

<HTML>
                                <HEAD>
                                <TITLE>Holiday Weekend</TITLE>
                                </HEAD>

                                <BODY>
                                <B>3 rooms available at special
      holiday weekend rates! </B>
                                <BR>Check in for a luxurious holiday
      weekend at these amazing prices.
                                <BR> Choose frome:

                                <TABLE>
                                <TR>
                                <TD>1)</TD>
                                <TD>Single Room</TD>
                                <TD>$ 100.00</TD>
                                </TR>

                                <TR>
                                <TD>2)</TD>
                                <TD>Double Room</TD>
                                <TD>$ 150.00</TD>
                                </TR>

                                <TR>
                                <TD>3)</TD>
                                <TD>Luxury Suite</TD>
                                <TD>$ 250.00</TD>
                                </TR>
                                </TABLE>

                                <BR> Call today for a reservation.
      Toll free number: 1-800-555-1212 </BODY>
                                </HTML>
                            

Example 14.2. Simple Java template

The following example demonstrates the generation of standard Java code and a number of options for changing the format of the generated code by making slight modifications to the template.

Note: The standard Java templates supplied with Poseidon for UML use defined indentation markers to format the code for better reading. The markers are of the format: $(__). These indentation markers are defined as variables that resolve to an empty string. They should never show up in the generated Java code. If you find that the generated code contains such text elements, please ensure that the markers are defined and used correctly in the template.

Below is an excerpt from the template used for generating the class and method declarations.

(A)

## Template for standard Java output

## .. snippet ..


#set ($vis          
   = $currentOp.getVisibilityAsString())
#set ($static       
   = $currentOp.getOwnerScopeAsString())

..

#set ($thrownClause 
   = $currentOp.getThrownExceptionsSignature())
#set ($name         
   = $currentOp.getNameAsString())
#set ($methodBody   
   = $currentOp.getMethodBody())

..

${vis}${static}${final}${synch}${return} 
${name}($params) $thrownClause {
  #renderMethodBody($currentOp.getMethodBody() 
  $currentOp.hasReturnType())
}

## .. snippet ..

One step you could take to modify the Java code generated by this example would be to enter a line break before the "$thrownClause" references in the template so that the thrown exceptions appear in a separate line of the method declaration. In the following example the opening bracket has also been moved to a separate line:

(B)

## Template for reformatted Java output

## .. snippet ..

${vis}${static}${final}${synch}${return} ${name}($params)

$thrownClause {
  #renderMethodBody($currentOp.getMethodBody() 
    $currentOp.hasReturnType())
}

## .. snippet ..

The effects of such a change become clear if we compare a bit of Java code generated on the basis of these simple variations (A and B):

(Java code based on A)

public static void main(String[] params)
  throws Exception {

  doSomething()

} 

(Java code based on B)

public static void main(String[] params)

throws Exception

{

  doSomething()

} 

2.2. Working with the Standard Templates

The standard templates supplied with Poseidon for UML can be used to generate Java and HTML code. The generated code is based on Class Diagrams only, but one may want to produce code from deployment diagrams or sequence diagrams. With the Professional Edition you can create your own templates to generate IDL files or C++ code.

The Java code generated on the basis of the standard Java templates is fully Java 2 compliant. The code can make use of all the features supported by Java 2, including exception handling, inner classes, and static initializers.

HTML code generated on the basis of the Standard HTML templates is simple HTML, similar to Javadoc. A separate page is generated for each class in a Class Diagram. As with the Java templates, the Professional Edition of Poseidon for UML allows you to modify the HTML templates to conform with your preferences and requirements.

2.3. Code Generation API

For a detailed description of the code generation API, please refer to the online API documentation (Javadoc) and the separate document describing the code generation framework. These files are part of the Developer and Professional distributions in the docs folder.

Also available are two demo plug-ins that show the capability of the code generation API and of the Poseidon plug-in API in general. The demo plug-ins are distributed as ready-to-run JAR files, along with the appropriate license keys. Also, the source code is distributed, including an ANT script for building the JARs. You may use these plug-ins as examples and as starting points for your own plug-ins. If you want to create your own plug-ins, please contact plugins@gentleware.com to receive a key for your plug-in.