Simple Types Generator

The simple types generator uses a 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 HibernateUserType binding on demand. Also the simple types implement the tagger interface org.jcoderz.commons.StrongType.

Type-Safe Enumerations

The mechanism of a type-safe enumeration is a pattern for a Java constant class under JDKs 1.4 and below, where no built in enum type is present (enums).

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>Class level comment.</description>
         <value description="Value Comment.">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>

         <!-- documentation -->
         <state name="start" type="start">
            <transition target="Submitted" name="Submit"/>
         </state>
         <state name="Submitted">
            <transition target="Postponed" name="Postpone"/>
            <transition target="Assigned" name="Assign"/>
            <transition target="Rejected" name="Reject"/>
         </state>
         <state name="InfoRequested">
            <transition target="Closed" name="Close"/>
            <transition target="Submitted" name="Resubmit"/>
         </state>
         <state name="Postponed">
            <transition target="Assigned" name="Assign"/>
         </state>
         <state name="Assigned">
            <transition target="Opened" name="Open"/>
         </state>
         <state name="Rejected">
            <transition target="Closed" name="Close"/>
         </state>
         <state name="Opened">
            <transition target="InfoRequested" name="Info Request"/>
            <transition target="Postponed" name="Postpone"/>
            <transition target="Assigned" name="Re-Assign"/>
            <transition target="Rejected" name="Reject"/>
            <transition target="Resolved" name="Resolve"/>
         </state>
         <state name="Resolved">
            <transition target="Accepted" name="Accept"/>
         </state>
         <state name="Accepted">
            <transition target="Closed" name="Close"/>
         </state>
         <state name="Closed"/>
      </enumeration>
   </typeSafeEnumerations>
</simpleTypes>

The name of the generated type-safe enumeration class is determined by the package and the classname attribute and the values of the enumeration are defined by the value tags.

You can add a description element to define the class level comment. To override the default generated documentation for the values add a attribute description to each value.

The state tags are used by the documentation tool-chain to create state diagrams via Graphviz. This feature is useful for modeling state transition diagrams in application domain models.

To generate a HibernateUserType binding add a user-type attribute to the enumeration element. As value you can choose between 'numeric', which creates a binding that stores the numeric (int) representation in the database or 'string' which generates a binding that stores the String representation of the enum in the database. In both cases the generated class name is the name of the enum class with UserType appended.

You can define discrete numeric representation for the enum. Therefore each value element must have a numeric attribute that defines the int representation of this value. To get a value independent constant name representation of the enum you can add a symbol attribute to the value element.

Restricted String

The concept of a restricted string is used to limit the number of characters that can be stored in a java.lang.String class.

The XML declaration of a restricted string class (org.jcoderz.commons.types.Foo) looks like this:

<simpleTypes>
   <!-- mandatory: classname, package, min-length, max-length -->
   <restrictedStrings>
      <restrictedString classname="Foo"
                        package="org.jcoderz.commons.types"
                        min-length="1"
                        max-length="1024"
                        user-type="true"
                        regex="[a-zA-Z]*">
      </restrictedString>
   </restrictedStrings>
</simpleTypes>

The name of the generated restricted string class is determined by the package and the classname attribute. The attributes min-length and max-length specify the length boundaries of the Java String. The user-type attribute defines whether a Hibernate User Type should be generated. The generated User Types are subclasses of StringUserTypeBase (Source). The regex value defines the regular expression pattern that is checked when creating instances of this class.

The restricted string can have a set of constants defined via constant elements within restrictedString. The constant must hold a name and value attribute. An optional attribute comment can be used to define the comment to be generated. The values to be used in constants must be valid in scope of the defined data type.

Restricted Long

<restrictedLongs>
    <restrictedLong
        classname="FooLong"
        package="org.jcoderz.commons"
        min-value="1"
        max-value="10">
        <constant
            name="CONSTANT_VALUE"
            value="5"
            comment="Additional Constant defined in the XML document."/>
    </restrictedLong>
</restrictedLongs>

Fix Point Number

The simple type fixPointNumber generates a fix point numeric that is backed by a long. You can omit the min-value and max-value declaration, in this case the maximum and minimum implied by the fraction-digits and total-digits is used (would be -999.99 to 999.99 in the below example). The generated HibernateUserType uses a BigDecimal? for database access via JDBC. We might add a binding that maps this to a (unscaled) long on request. Since the type is backed by a long the maximum unscaled value this type can hold is Long.MAX_VALUE and the lowest value is Long.MIN_VALUE. This implies a maximum for total-digits is 18 if you need the full range or 19 if you set max-value to Long.MAX_VALUE and min-value to Long.MIN_VALUE. fraction-digits must not be below 0 or higher than total-digits.

  <fixPointNumbers>
    <!-- mandatory: classname, package, fraction-digits, total-digits -->
    <fixPointNumber
        classname="SampleFixPoint"
        package="org.jcoderz.commons.types.samples"
        min-value="-100.50"
        max-value="100.00"
        fraction-digits="2"
        total-digits="5"
        user-type="true">
        <constant
          name="CONSTANT_VALUE"
          value="5.00"
          comment="Additional Constant defined in the XML document."/>
    </fixPointNumber>
  </fixPointNumbers>

Value Object - Composite Type see ValueObject

The concept of a value object is related to the pattern of the Data Transfer Object (DTO). The difference is that the value objects can be generated as mutable or immutable Java classes.

To support an easy way to generate Javadoc tags since BUILD_405 you can add a xdoclet element next to the description. This element is then used to generate Javadoc tags e.g. xdoclet tags for hibernate. The description of the members should be placed in a description tag as well and not be provided as plain text content of the member element. The use of other xml tags (e.g. for html formatting) is not permitted here.

With BUILD_457 2 new member attributes had been introduced. Main purpose is to ease the generation of composite types that can be used in combination with hibernate. identity-independent excludes - if set - the member from the calculation of the hash-code and omits it in the equals comparison. Details on the need of this can be found on the Hibernate site. The 2nd new attribute is setter-visibility where the visibility of the setter of the member can be changed from its default public. The value of the attribute must simply be set the appropriate Java key word. Use the empty string for default accessibility.

With BUILD_637 a new attribute baseclass is supported for the valueObject element. The given value is used as baseclass 'extends ...' of the generated value object. There are several limitations related to this functionality. The baseclass must have a valid equals() and hashCode() implementation as well as an default constructor taking no arguments. The generated class will not get a copy constructor and the generated constructors will not support to fill the possible members of the baseclass.

The XML declaration of a value object class, called org.jcoderz.commons.foo.types.FooValueObject, looks like this:

<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" dynamic-update="true"/>
           <hibernate.cache usage="read-only"/>
         </xdoclet>
         <member name="Id"
                 type="long"
                 identity-independent="true"
                 setter-visibility="protected">
           <description>unique identifier for Foo</description>
           <xdoclet>
             <hibernate.id generator-class="native"
               unsaved-value="-1"/>
           </xdoclet>
         </member>
         <member name="Creation Date"
                 type="org.jcoderz.commons.types.Date">
            <description>creation date of Buz</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>
         <member name="Participants"
                 type="java.util.List"
                 initial-value="new java.util.ArrayList()"
                 final="true">
            <description>List of all Merchants</description>
         </member>
      </valueObject>
   </valueObjects>
</simpleTypes>

The name of the generated value object class is determined by the package and the classname attribute. The serializable attribute defines whether the generated class implements the Serializable interface. The the attribute is present the generated class will implement the java.io.Serializable interface. If the final attribute is set to the value 'true', the generated class is immutable. From the value of the description tag the class' Javadoc comment is created. The member tag defines the class members, where name is the name of a member variable which determines the name of the getter and setter method. The optional attribute initial-value can be used to initialize a member during construction of the class. Also you can set members to final which will then be used for appropriate constructor generation. Also final members for sure do not get a setter method generated. The value of the description tag below member is used as Javadoc tag as well. On both valueObject and member level a xdoclet sub-element will be used to generate xdoclet tags into the Javadoc. The name of further sub-elements will be turned into xdoclet tags ('@' prepended) and its attributes will be converted into xdoclet parameters of the same name. To create an empty xdoclet parameter with no value assigned use the empty string as attribute value. The sample shows the usage of a Hibernate User Type for member Comment where CommentUserType is a generated subclass of StringUserTypeBase.

Usage

The usage of the simple types generator from Ant is described in the Javadoc of the org.jcoderz.commons.taskdefs package.