-
Notifications
You must be signed in to change notification settings - Fork 1
SimpleTypesGenerator
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
.
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] (http://java.sun.com/j2se/1.5.0/docs/guide/language/enums.html).
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.
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. 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.
<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>
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>
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.
The usage of the simple types generator from Ant is described in the Javadoc of the org.jcoderz.commons.taskdefs
package.