The version generator |
A versioned object is an object with a composed primary key: We call the first part the version ID and the second part the version number. Objects with the same ID are called versions of the object. If the versioned object is stored in a single SQL table, a new version can obviously be derived as follows:
The current version of the version generator has some restrictions. In particular the following rules apply:
T1
, T2
, T3
, ... be the
tables being cloned.T3
must
not have a reference to T3
.T2
and T3
may reference T1
, but neither T2
nor
T3
may reference T1
nor may T3
reference T2
.Column updaters are used to perform the required modifications for the in-memory rows. For example, there is a column updater that updates a foreign keys value from an object that has already been cloned to its clone. Column updaters are implementing the interface VersionGenerator.ColumnUpdater.
The main thing to understand when writing a column updater is that it is not invoked at runtime, but as a part of the source generation stage. It emits Java code taking an object array as input and modifying the array. As an example, we demonstrate a very basic column updater, which is simply incrementing the version number. We assume that the version number is an integer, stored in the tables second column:
public class VerNumIncrementer implements VersionGenerator.ColumnUpdater { public void update(JavaMethod pMethod, VersionGenerator.TableInfo pTableInfo, DirectAccessible pConnection, DirectAccessible pMap, DirectAccessible pRow) { pMethod.addLine(pRow, "[2] = new Integer(((Integer) ", pRow, "[2]).intValue()+1);"); } }The column updaters arguments are as follows:
Name | Description |
---|---|
pMethod | The method being generated. |
pTableInfo | Holds the generators view of the table being
cloned by the method pMethod . The most important property
is the table property, which returns an instance of
Table with the table name
and column list. |
pConnection | A variable name which is holding an open database connection in the generated source. |
pMap | A variable name with a map used to note the column which have already been cloned. The tables keys are the primary keys before cloning, and the tables values are the keys after cloning. The map is used to adjust foreign key references. |
pRow | A variable name representing an array of objects, one for any column in the table. The object types correspond to the column data types: For example, a VARCHAR or CHAR column is mapped to a String, INT, or BIGINT, columns are mapped to Integer and Long, respectively, and so on. |
To use the version generator, you need a set of tables (subject to the limitations described above). For any table, you also need a ColumnUpdater. If you have that, the generator is invoked like this:
import net.sf.jaxme.js.JavaQNameImpl; import net.sf.jaxme.js.JavaSource; import net.sf.jaxme.js.JavaSourceFactory; import net.sf.jaxme.js.pattern.VersionGenerator; import net.sf.jaxme.js.pattern.VersionGenerator.ColumnUpdater; import net.sf.jaxme.sqls.Table; Table[] tables; // Supplied by you ColumnUpdater updaters; // Supplied by you, same length than tables array JavaSourceFactory factory = new JavaSourceFactory(); VersionGenerator vgen = new VersionGenerator(); vgen.setGeneratingLogging(true); for (int i = 0; i < tables.length; i++) { vgen.addTable(tables[i], updaters[i]); } JavaSource js = factory.newJavaSource(JavaQNameImpl.getInstance("com.foo", "Bar"), JavaSource.PUBLIC); vgen.getCloneMethod(js);
You might replace the VersionGenerator with a subclass, because the above
code would emit logging statements using the
net.sf.jaxme.logging package.
If you do not favour this, replace the methods logEntering
,
logExiting
, logFinest
, logFinestEntering
,
and logFinestEntering
with your own implementations.