Skip to main content
jCoderZ.org / Java tooling collective
  1. Home
  2. fawkeZ
  3. Wiki
  4. Simple types generator

fawkeZ wiki / last edited 13 December 2006

Simple types generator

Strong, immutable Java types generated from a compact XML declaration, with optional Hibernate bindings.

The simple types generator uses an XML notation to define type safe enumeration classes, restricted strings and value objects. All simple types are based on the concept of an immutable object and can support a Hibernate user type binding on demand. The generated types also implement the tagger interface org.jcoderz.commons.StrongType.

Type safe enumerations

A type safe enumeration is a pattern for a Java constant class under JDK 1.4 and below, where no built in enum type is present. The XML declaration of a type safe enumeration class called org.jcoderz.commons.types.JiraState looks like this:

<simpleTypes>
  <typeSafeEnumerations>
    <enumeration classname="JiraState"
                 package="org.jcoderz.commons.types">
      <description>Ticket state for the issue tracker.</description>
      <value description="Newly filed.">Submitted</value>
      <value>InfoRequested</value>
      <value>Postponed</value>
      <value>Assigned</value>
      <value>Rejected</value>
      <value>Opened</value>
      <value>Resolved</value>
      <value>Accepted</value>
      <value>Closed</value>
      <state name="Submitted">
        <transition target="Postponed" name="Postpone" />
        <transition target="Assigned" name="Assign" />
        <transition target="Rejected" name="Reject" />
      </state>
      <state name="Assigned">
        <transition target="Opened" name="Open" />
      </state>
    </enumeration>
  </typeSafeEnumerations>
</simpleTypes>

The generated class name comes from the package and the classname attribute. The values of the enumeration are defined by the value elements. A description element sets the class level Javadoc comment; a description attribute on a value overrides the default comment for that value.

The state elements are used by the documentation tool chain to create state diagrams with Graphviz. This is useful for modelling state transitions in an application domain model.

Hibernate binding

To generate a Hibernate user type binding, the enumeration is marked as persisted and the storage form is chosen: the numeric representation stores the integer value of the enum in the database, while the string representation stores its name. In both cases the generated class name is the name of the enum class with the suffix UserType. A discrete numeric representation can be defined per value when the numeric form is used.

Restricted strings

A restricted string limits the number of characters that can be stored in a Java string. The generator accepts a class name, a package, a minimum length and a maximum length. It can also generate a Hibernate user type, and it can enforce a regular expression pattern when instances are created.

Constants can be declared inside the restricted string element. Each constant has a name and a value, plus an optional comment for the generated Javadoc. The value must be valid for the declared length and pattern.

Restricted long

The restricted long type works the same way for whole numbers. The declaration supplies a class name, a package, a minimum value and a maximum value. Additional constants can be declared with a name, a value and a comment.

Fix point numbers

The fix point number type generates a fixed point numeric value backed by a long. The declaration supplies a class name, a package, the number of fraction digits and the total number of digits. Minimum and maximum values are optional; when they are omitted, the range implied by the fraction and total digits is used. A total of 5 digits with 2 fraction digits gives a range of 999.99 in either direction.

The generated Hibernate user type uses a big decimal for database access through JDBC. Because the value is backed by a long, the largest unscaled value the type can hold is the maximum long value.

Value objects

A value object is related to the data transfer object pattern. The difference is that value objects can be generated as mutable or immutable Java classes. The generator supports Javadoc tags through an xdoclet element next to the description, which is useful for Hibernate annotations.

<simpleTypes>
  <valueObjects>
    <valueObject classname="FooValueObject"
                 package="org.jcoderz.commons.foo.types"
                 serializable="serializable"
                 final="false">
      <description>The Foo is documented here.</description>
      <xdoclet>
        <hibernate.class table="FooTable" />
      </xdoclet>
      <member name="Id" type="long">
        <description>Unique identifier for Foo.</description>
      </member>
      <member name="Comment" type="Comment">
        <description>Comment describing the value object.</description>
        <xdoclet>
          <hibernate.property type="org.jcoderz.commons.foo.types.CommentUserType" />
        </xdoclet>
      </member>
    </valueObject>
  </valueObjects>
</simpleTypes>

The serializable attribute makes the generated class implement the serializable interface. When the final attribute is true, the generated class is immutable. The description of the class becomes its Javadoc comment, and the member elements define the fields, their types and their comments.

Member options

  • Initial value. A member can declare an initial value, used during construction of the class.
  • Final members. Marking a member as final also affects constructor generation and means no setter is generated.
  • Identity independent members. A member can be excluded from hash code calculation and from the equals comparison. This is useful when a database identifier is assigned after the object is created.
  • Setter visibility. The visibility of a generated setter can be changed from the default public visibility.
  • Base class. A value object can extend a base class, provided that class has a valid equals and hash code implementation and a constructor with no arguments. The generated class will not receive a copy constructor in that case.

Using the generator

The generator runs from Ant. The task definitions live in the org.jcoderz.commons.taskdefs package, and its Javadoc describes the available attributes. Because the generator runs with every compile, only the XML input is stored in the repository; the Java source is produced by the build.

References