Probably the
best way to learn how to use JGT is to look at the example code. Its
provided as a suite of JUnit tests, located in the directory tests/net/sourceforge/jgt/examples.
The tutorial will dicuss the code in these tests.
To get started, here is a very simple example that does nothing more
than copy a property from one object to another:
public void testSimple_ForwardMapping() throws Exception {
//Create two different object graphs
PersonA roota = new PersonA();
PersonB rootb = new PersonB();
roota.setName("Tom");
rootb.setName("Jerry");
/**
* Create configuration data for the transformation. We state we want to use the "SimpleRuleSet"
* transformation rule set. This rule set must be implemented as an XML file
* called "SimpleRuleSet.jelly"
*/
TransformationContext context = new TransformationContext("SimpleRuleSet");
GraphTransformer.getInstance().transformGraphs(roota,rootb,context);
assertEquals("Tom",rootb.getName());
assertEquals("Tom",roota.getName());
}
Here is the SimpleRuleSet.jelly XML rule set:
<?xml version="1.0"?>
<j:jelly trim="false" xmlns:j="jelly:core"
xmlns:graph="jelly:net.sourceforge.jgt.jelly.JGTTagLibrary">
<graph:mapping name="names">
<graph:set name="name"/>
</graph:mapping>
</j:jelly>
JGT works on two graph, graph A and graph B. Each graph
is passed to JGT as a single root node. So the first thing the example
above does is to configure two very simple graphs and get a reference to
the root node for each (roota and rootb).
JGT also works on a set of transformation rules that define
how to map from graph A to graph B and back again. This is what the
TransformationContext object is for. In its simplest form, it takes
nothing more than the name of a rule set that you have defined somewhere
else. In this example we want to use SimpleRuleSet.
The interface to JGT is GraphTransformer.getInstance().transformGraphs().
It takes the root node to graph A, the root node to graph B and the
tranformation context. Internally, it attempts to locate a rule set
file called SimpleRuleSet.jelly as a resource on the classpath. If
it fails to locate this, you will get an illegal argument exception. If
it succeeds to locate the resource, it will perform the transformation rules
in that file to the two graphs provided.
SimpleRuleSet.jelly defines the rule set required to copy
a property from one graph to another. The first two lines and the last
two lines are required by all JGT rule sets. The graph:mapping bit
is where the JGT rule begins.
JGT rule sets are sectioned into named groups. graph:mapping
is what defines the sectioning. The reason for this is that sections
in a rule set can be independently activated/deactivated to allow fine grain
specification of transformation requirements, which are likely to be different
across use cases. So, this mapping line above says "there is a mapping
called names. You can specify the mappings you want to execute as a
list of names to TransformationContext.setMappings(). The default is
for all mappings to execute, which is what will happen in this example.
graph:set, as written above, states that there is a property
with the same name on each graph and I want to synchronize their values.
The direction of synchronization is either forward (graph a to graph
b) or reverse (graph b to graph a). This value is specified in the context
object (setForwardMapping() and setReverseMapping()) and defaults to forward.
graph:set can also deal with properties with different names on each
graph, as shown later.
So, the bottom line after all this work is the equivalent
of this java code.
PersonA roota = new PersonA();
PersonB rootb = new PersonB();
roota.setName("Tom");
rootb.setName("Jerry");
if ( ! roota.getName().equals(rootb.getName())) {
rootb.setName(roota.getName());
}
Hardly very exciting, so lets move on. Or you can check
out a more complete example here.