Overview

This is an add-on set of Torque Template files that modifies the Torque DataDTD task to generate two additional files, a Betwixt mapping file and a matching DTD file.

The Apache Common Betwixt package ( http://jakarta.apache.org/commons/betwixt ) provides a way of turning Beans into XML and to load Beans with data from XML. Betwixt can work in two main ways. It can use Bean Introspection to decide how to do this or it can use a "mapping file" that defines what properties and methods to use in a class. This second method allows Betwixt to work for Java classes that are bean-like but not bean compliant, like Torque's OM record files.

This add-on takes Torque's XML schema and produces a single Betwixt mapping file that maps all the Torque Generated classes for use by Betwixt. There are a variety of ways that this can be used, from adding individual OM class writeXML/readXML methods to using the Torque Betwixt XML Runtime code that supports importing / export data from / to Databases via Torque.

In addition, this add-on will cause the DataDTD task to generate a DTD file that matches the XML syntax used by Betwixt to export and load Torque objects. This allows for XML input to be syntax checked for validity and user typos. It also can act as a limited schema version check. E.g., if the DTD is versioned, the DTD specified on XML defines the schema version it was created from.

Using Betwixt and Torque generated mapping files eliminates the need to write any XML parsing code that has to be maintained as an application's schema changes over time.

Installation

Note: This is based on using Torque V3.2.1 or greater.

First, decide where you want to place your Template add-ons in your project, e.g. src/torque-local-mods or the like.

Place the torque-betwixt-templates-1.0-rc-override.jar (or current version) in this directory.

Next, tell the Torque build script were to find this by adding a line like:

    torque.override.dir = ${torque.output.dir}/torque-local-mods

to your build.properties (or project.properties). Make sure this setting points to the correct directory.

Finally, add the following lines to your build.properties file:

#Betwixt settings

# Generate betwixt map and dtd support files if set.
torque.betwixt.generate = true

# Specify the directory to create the support files in (relative
# to the outputDirectory specified in the Task properties.
# torque.betwixt.dir = ./../java/org/my/package/betwixt

# A file that will be included at the top of the DTD.  Useful
# for defining app specific non-DB elements.  Location is
# relative to the outputDirectory specified in the datadtd target.
# torque.betwixt.Dtd.extraFile = ./../xml/local.dtd

# A comma separated (and no spaces) list of elements to add to
# the dataset element children list (probably defined in the
# file above)
# torque.betwixt.Dtd.extraElements = membership

# Options to allow on dataset action attribute.
# Default is CDATA #IMPLIED (allows anything)
# torque.betwixt.Dtd.dataset.actions = ( addUpdate | add | update | delete ) "addUpdate"

# A file that will be included at the top of the Betwixt map file.  Useful
# for defining mapping for app specific non-DB classes.  The location is
# relative to the outputDirectory specified in the datadtd target.
# torque.betwixt.Map.extraFile = ./../xml/local.betwixt

# A pair of matched lists used to allow XML elements to have more user-friendly
# names than the default table names. Note that the tableName format is the
# table's Java name with first letter lowercased, e.g myTable.
#
# Examples:
# torque.betwixt.table.names = myTable,anotherTable
# torque.betwixt.xml.names   = to-do,would-be-nice
# torque.betwixt.table.names = users
# torque.betwixt.xml.names   = user

# The class which impliments the default dataset element (default is
# org.apache.torque.betwixt.Dataset)
# torque.betwixt.dataset.class = org.apache.torque.betwixt.Dataset
      

Configuration

The minimum you need to do is to set the torque.betwixt.generate property to a any value (like yes or true). This will cause a <DB-Name>.betwixt mapping file and a <DB-Name>-betwixt.dtd file to be created in the outputDirectory specified on the DataDTD task. (The default is the schema directory).

You can control where these files are created by using the torque.betwixt.dir property. This can be nice if you want to place them in a Java package to be included in a generated jar.

The remaining properties can be used to add to or slightly modify the output to meet your application needs. For example, if you have a table named Users and want the XML Element name to be User, you can use the torque.betwixt.table.names and torque.betwixt.xml.names properties.

Or if you want to include some other Betwixt class mappings in the generated mapping file, you can use the torque.betwixt.Map.extraFile property. You should also look at the torque.betwixt.Dtd.extraFile and torque.betwixt.Dtd.extraElements properties to include these classes in the generated DTD.

Usage

For complete framework for exporting and importing data to and from XML, see the Torque Betwixt XML Runtime package.

But for those who want to roll their own here's some examples of the basic Betwixt code needed to write and read a single Torque object using the mapping file. To convert this to something more useful, you'll need to read up on Betwixt collection beans and other items. (or take a look at the above package source...).

Note that this requires the SNAPSHOT version of Betwixt 0.8.

First here's a simple Torque Database Schema snippet:

<table name="TorqueOMCLass" ...>
   <column name="col1" .../>
   <column name="col2" .../>
   <column name="col3" .../>
</table>
      

Here's some code to write out data from a single TorqueOMClass object.

    // Write a single TorqueOMClass object out as an XML snippet.

    FileWriter outputWriter = new FileWriter( testFile );
    InputSource mapSource = new InputSource( mappingFile );

    BeanWriter beanWriter = new BeanWriter(outputWriter);
    beanWriter.getXMLIntrospector().register(mapSource);

    beanWriter.getBindingConfiguration().setMapIDs(false);
    beanWriter.enablePrettyPrint();

    // This will just write an XML 'snippet' for the torqueObject
    beanWriter.write( torqueOMClass );
    beanWriter.close();
      

This will produce output like:

    <torqueOMClass>
        <col1>value1</col1>
        <col2>value3</col1>
        <col3>value3</col1>
    </torqueOMClass>
      

To read this (not well formed) XML back in use:

    // Create a new TorqueOMClass object with values specified in XML.

    InputSource mapSource = new InputSource( mappingFile );

    BeanReader beanReader = new BeanReader();
    beanReader.registerMultiMapping(mapSource);

    FileReader inputReader = new FileReader( testFile );
    TorqueOMClass torqueObject = (TorqueOMClass) =
                    beanReader.parse( inputReader );
    beanReader.close();
      

This will result in a "new" TorqueOMClass object populated with the data. You can also read in "well formed" XML (with proper headers and DTD definition) and use Betwixt options to have the XML syntax checked against the DTD file.

Conflicts With other Add-ins

This add-on only modifies the data/Control.vm template which is the main controller for the datadtd task. Any other add-in which modifies this task will need to have the various changes in this file reconciled into a new Controller.vm

Building

Maven or Ant build file. This is a Velocity templates only project so there are not real dependancies.