The Apache Jakarta Project Jakarta HiveMind Project
 
   

Contribution Processing Rules

The concept of performing a rules-directed conversion of elements and attributes into Java objects was pioneered (to my knowledge) in the Jakarta Digester framework (which started inside Tomcat, moved to Struts, and is now available on its own).

The technique is very powerful, even in the limited subset of Digester provided by HiveMind (over time, the number of available rules will increase).

Rules

Rules are attached to <element>s. Each rule object has two methods: the begin() method is invoked when the element is first encountered. The content of the element is then processed recursively (which will involve more rules). Once that completes, the end() method is invoked.

Note: begin() is invoked in the order that rules are defined within the <rules> element. end() is invoked in inverse order. This rarely makes any difference.

Element processing is based on an object stack. Several rules will manipulate the top object on the stack, setting properties based on attributes or content. The <create-object> rule will instantiate a new object at begin() and pop it off the stack at end() .

In several cases, rule descriptions reference the parent and child objects. The top object on the stack is the child, the object beneath that is the parent. The <set-parent> and <invoke-parent> rules are useful for creating hierarchies of objects.

create-object

The <create-object> rule is used to create a new object, which is pushed onto the stack at begin(). The object is popped off the stack at end(). <create-object> is typically paired up with <invoke-parent> to connect the new object (as a child) to a parent object.

Attribute Type Required ? Description
class string yes The complete class name of the object to create. The class must be public, and have a no-arguments public constructor.

custom

The <custom> rule is used to provide a custom implementation of the Rule interface. Note that any such rules must not contain any individual state, as they will be reused, possibly by multiple threads.

Attribute Type Required ? Description
class string yes The complete class name of the class implementing the Rule interface.

invoke-parent

The <invoke-parent> rule is used to connect the child (top object on the stack) to its parent (the next object down). A method of the parent is invoked, passing the child as a parameter. This invocation occurs inside the rule's begin() method; to ensure that the child object is fully configured before being added to the parent place this rule after all properties of the child object have been configured.

Attribute Type Required ? Description
method string yes The name of the method to invoke on the parent object.
depth number no The depth of the parent object within the object stack. The top object (the child) is at depth 0, and default depth of the parent is 1.
Warning
Top level elements should include an <invoke-parent> rule, and specify the method as addElement. This adds the created, configured object to the list of contributed objects for the <contribution> (or for service factories, adds the object as a parameter).

push-attribute

The <push-attribute> rule reads an attribute, converts it with a translator, and pushes the result onto the stack. It will typically be combined with a <invoke-parent> to get the pushed value added to the configuration point elements (or to some parent object).

Attribute Type Required ? Description
attribute string yes The name of the attribute to read.

read-attribute

The <read-attribute> rule reads an attribute from the current element, optionally translates it (from a string to some other type), and then assigns the value to a property of the top object on the object stack.

Attribute Type Required ? Description
property string yes The name of the property of the top object on the stack to update.
attribute string yes The name of the attribute to read.
skip-if-null boolean no If "true" (the default), then an omitted attribute will be ignored. If "false", the property will be updated regardless.
translator string no A translator that overrides the attribute's translator.

read-content

The <read-content> rule is similar to <read-attribute>, except it concerns the content of the current element (the text wrapped by its start and end tags).

Attribute Type Required ? Description
property string yes The name of the property of the top object on the stack to update.

set-module

<set-module> is used to set a property of the top object on the stack to the module which made the contribution. This is often used when some other attribute of the contribution is the name of a service or configuration extension point (but it is advantageous to defer access to the service or configuration). The module can be used to resolve names of services or configurations that are local to the contributing module.

Attribute Type Required ? Description
property string yes The name of the property of the top object to update with the contributing module.

set-parent

The <set-parent> rule is used to set a property of the child object to parent object. This allows for backwards connections from child objects to parent objects.

Attribute Type Required ? Description
property string yes The name of the property of the child object to set.

set-property

The <set-property> rule is used to set a property of the top object to a preset value.

Attribute Type Required ? Description
property string yes The name of the property of the child object to set.
value string yes The value to set the proeprty to. The is interpreted as with the smart translator, meaning that conversion to normal Java types (boolean, int, etc.) will work as expected.

Translators

Commonly, it is necessary to perform some translation or transformation of string attribute value to convert the value into some other type, such as boolean, integer or date. This can be accomplished by specifying a translator in the <attribute> element (it also applies to element content, with the content-translator attribute of the <element> element).

A translator is an object implementing the Translator interface. The translator value specified in a rule may be either the complete class name of a class implementing the interface, or one of a number of builtin values.

Translators configurations consist of a translator name, and an optional initalizer string. The initializer string is separated from the translator id by a comma, ex: int,min=0 (where min=0 is the initializer string). Initializer strings are generally in the format of key=value[,key=value]* ... but each Translator is free to interpret the initializer string its own way.

The following sections describe the basic translators provided with the framework. You can add additional translators by contributing to the hivemind.Translators configuration point.

bean

The bean translator expects its input to bean in the form service-id:locator. The service-id references a service implementing BeanFactory.

Note
This translator is contributed by the hivemind.lib module.

boolean

The boolean translator converts an input string into a boolean value. "true" is translated to true, and "false" to false.

A default value is used when the input is blank. Normally, this default is false, but the "default" key in the initializer can override this (i.e., boolean,default=true).

class

The class translator converts a class name into a Class object. The value must be a fully qualified class name. A null input value returns null.

Note
This translator is hard-coded, and does not appear in the hivemind.Translators configuration point.

configuration

The configuration translator converts an input value into a configuration point id, then obtains the elements for that configuration point as a List. The id may be fully qualified, or a local id within the contributing module.

A blank input value returns null.

double

The double translator converts the input into an double precision floating point value. It recognizes three initializer values:

  • default: the default value (normally 0) to use when the input is blank
  • min: a minimum acceptible value
  • max: a maximum acceptible value

enumeration

The enumeration translator converts input strings into enumerated values. Enumeration requires an initializer string, with a special format:
enumeration,class-name,input=field-name[,input=field-name]*

That is, the initializer begins with the name of the class containing some number of public static fields. Input values are mapped against field names. Example:
enumeration,java.lang.Boolean,yes=TRUE,no=FALSE

If the input is null or empty, then the translator returns null.

id-list

Translates a comma-seperated list of ids into a comma-seperated list of fully qualified ids (qualified against the contributing module). Alternately, passes the value * through as-is. Id lists are typically used to establish ordering of items within a list, as with <interceptor>.

instance

The object translator converts a fully qualified class name into an object instance. The class must implement a public no-arguments constructor.

int

The int translator converts the input into an integer value. It recognizes three initializer values:

  • default: the default value (normally 0) to use when the input is blank
  • min: a minimum acceptible value
  • max: a maximum acceptible value
Note
This translator is hard-coded, and does not appear in the hivemind.Translators configuration point.

long

The long translator converts the input into an long integer (64 bit) value. It recognizes three initializer values:

  • default: the default value (normally 0) to use when the input is blank
  • min: a minimum acceptible value
  • max: a maximum acceptible value

object

The object translator is allows the caller to provide an object value in a multitude of ways. The object translator inverts the normal roles; the caller has all the power in determining how to interpret the value, and the schema takes whatever value shows up. The object translator is driven by the hivemind.ObjectProviders configuration.

qualified-id

Translates an id into a fully qualified id (qualified against the contributing module's id).

resource

The resource translator is used to find a resource packaged with (or near) the module's deployment descriptor. The input value is the relative path to a file. The translator converts the input value to a Resource for that file.

If the file doesn't exist, then an error is logged. If a localization of the file exists, then the Resource for that localization is returned.

service

The service translator is used to lookup a service in the registry. The input value is either a local service id from the contributing module, or a fully qualified service id.

Note
This translator is hard-coded, and does not appear in the hivemind.Translators configuration point.

service-point

The service translator is used to lookup a service point (not a service) in the registry. The input value is either a local service id from the contributing module, or a fully qualified service id.

smart

The smart translator attempts an automatic conversion from a string value (the attribute value or element content) to a particular type. It determines the type from the property to which the value will be assigned. Smart translator makes use of the JavaBeans's PropertyEditor class for the conversion, which allows easy this translator to be used with most common primitive types, such as int, short and boolean. See the SmartTranslator documentation for more details.

In general, the smart translator is the useful for most ordinary Java type properties, unless you want to specify range constraints.

It recognizes one initializer value:

  • default: the default value to use when the input is blank
Note
This translator is hard-coded, and does not appear in the hivemind.Translators configuration point.