CreateNodeEvent instance for each constructed node as follows:
public class CreateNodeEvent {
def name
def node
def parent
def isRoot // set to true, if the new node is a root node
}
If not a root node, the closure should return the node, or possibly a different node, when it is done.
Using a Build Visitor to Build a List of Root Nodes
An example closure that builds a list of all root nodes might be:
{ if(isRoot) { myList << it.node }; it.node }
In fact, I thought that usage might be so common that I included another set of
buildList methods that returns a list of root nodes for you.I'd also thought about exposing the
ObjectGraphBuilder.postNodeCompletion() method, but it doesn't give you the node name, which is sometimes useful to have. It also doesn't tell you whether you're dealing with a root node (though you can probably derive that from the fact that parent == null for a root node.)Using a Build Visitor to Build a Map of Root Nodes
Here's another build visitor example: say I have classes
Order and OrderLine as follows and I want to use MetaBuilder to read Orders from a file into a map called orders, keyed on id:A Hibernate Example
class OrderLine {
def upc
def qty
def price
}
class Order {
def id
def lines = []
}
MetaBuilder mb = new MetaBuilder(getClass().getClassLoader())
mb.define {
order(factory: Order) {
properties {
id(req: true)
}
collections {
lines {
line (factory: OrderLine) {
properties {
upc(req: true)
qty(req: true)
price(req: true)
}
}
}
}
}
}
def orders = [:]
mb.build( { if(it.isRoot) { orders[it.node.id] = it.node }; it.node }, new File("orders.mb").toURL() )
Andres Almiray's recent blog post on using
ObjectGraphBuilder to create Grails fixtures inspired this next example, which extends the previousexample to insert each object into a database using Hibernate:
Final Thoughts
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction()
mb.build( { if(it.isRoot) { session.save(it.node) }; it.node }, new File("orders.mb").toURL() )
session.getTransaction().commit()
One of the benefits of this feature is that it enables you to process large numbers of build objects without having to incur the overhead of building a list to contain them all.
