groovytools.builder
Class MetaBuilder

java.lang.Object
  extended by groovytools.builder.MetaBuilder
Direct Known Subclasses:
MetaConfigBuilder

public class MetaBuilder
extends Object

MetaBuilder is a builder that uses schemas to more conveniently and correctly build object hierarchies.

Usage

MetaBuilder is easy to use. Just follow these steps:
  1. Create a MetaBuilder instance.
  2. Define your schemas with define(groovy.lang.Closure).
  3. Build your objects with build(groovy.lang.Closure, groovy.lang.Closure).

Example

Here is a very simple example demonstrating the steps above:
 // Create a MetaBuilder
 MetaBuilder mb = new MetaBuilder()

 // Define a schema
 mb.define {
     invoice {
         collections {
             items {
                 item {
                     properties {
                         qty(req: true)
                     }
                 }
             }
             payments {
                 payment {
                     properties {
                         amt(req: true)
                     }
                 }
             }
         }
     }
 }

 // Build an object.
 mb.build {
     invoice {
         items {
             item(qty: 1)      // two equivalent ways to
             item { qty = 20 } // set property values
         }
         payments {
             payment(amt: 100.00)
         }
     }
 }
 

The MetaBuilder Meta-Schema

The schemas that may be defined are governed by the following meta-schema. Note, '%' is used to stand for any sequence of non-whitespace characters:
 // default factories
 def schemaNodeFactory = new MetaBuilder.SchemaNodeFactory()
 def collectionSchemaNodeFactory = new MetaBuilder.CollectionSchemaNodeFactory()

 // some useful check closures
 def nullOrBoolean = { v -> v == null || v instanceof Boolean }
 def nullOrClosure = { v -> v == null || v instanceof Closure }
 def nullOrStringOrClosure = { v -> v == null || v instanceof String || v instanceof Closure }
 def nullOrStringOrClassOrFactoryOrClosure = { v -> v == null || v instanceof String || v instanceof Class || v instanceof Factory || v instanceof Closure }
 def nullOrStringOrSchemaNode = { v -> v == null || v instanceof String || v instanceof SchemaNode }

 def metaSchema = '%'(factory: schemaNodeFactory) {
     properties() {
         schema(check: nullOrStringOrSchemaNode )
         factory(check: nullOrStringOrClassOrFactoryOrClosure )
         check()
     }
     collections() {
         collections(factory: schemaNodeFactory) {
             '%'(factory: collectionSchemaNodeFactory) {
                 properties(factory: schemaNodeFactory) {
                     collection(check: nullOrStringOrClosure)
                     min(check: nullOrInt)
                     max(check: nullOrInt)
                     size(check: nullOrStringOrClosure)
                     key(check: nullOrStringOrClosure)
                     add(check: nullOrStringOrClosure)
                 }
                 '%'(shema: metaSchema)
             }
         }
         properties(factory: schemaNodeFactory) {
             '%'(schema: metaSchema)
                 properties() {
                     property(check: nullOrStringOrClosure)
                     req(check: nullOrBoolean)
                     def()
                     min()
                     max()
                     // Inherited from metaSchema:
                     // schema()
                     // factory()
                     // check()
                 }
             }
         }
     }
 }
 

Schema Attributes

The following table describes the schema attributes you may use when defining your own schema using MetaBuilder's default meta-schema. Values may be of type: literal, object,
Class and/or Closure.

Only one value may be specied for each property at a time.

Name Description Literal Object Class Closure
schema Allows a schema to inherit and extend the properties and collections of another schema. See below. The name of another schema. Optional. The named schema does not have to be previously defined. A previously defined schema object. n/a n/a
factory Specifies the factory to use for building nodes. Optional. The default factory builds SchemaNodes. A fully qualified class name for direct instatiation with Class.newInstance() . A Factory object. A Class for direct instatiation with Class.newInstance(). A Closure returning an object of the form
  • { -> ...}
  • {n -> ...}
  • {n, v -> ...}
  • {n, v, a -> ...}
where
  • n is the name of the node
  • v is the value of the node (may be null)
  • a is a map of the node's attributes (may be empty)
check Used to specify a check on the value of the property, which will result in an exception if the check fails. Optional. Any object or literal. The result of the check is logically equivalent to the result of executing the Groovy switch:
     switch(value) {
         case check: return true
     }
     return false
 
collection Used to identify or access the actual collection name. Optional. The default is to access the collection using the node's name. A property or field name n/a n/a A Closure returning the collection of the form
  • {o -> ...}
where
  • o is the owner of the collection
min (collection) Used to specify the minimum collection size. Optional. The default is no minimum. An int greater than or equal to 0. n/a n/a n/a
max (collection) Used to specify the maximum collection size. Optional. The default is no maximum. An int. n/a n/a n/a
size Used to specify an alternative way to retrieve the size of a collection. Optional. The default is to access the collection using the node's name. A property or field name n/a n/a A Closure returning the size of the form
  • {o -> ...}
where
  • o is the owner of the collection
key When collection is a Map, key must be defined to return the key to be used to add an object to children to the collection unless add is also specified with two arguments. A property or field name n/a n/a A Closure of the form
  • {c -> ...}
where
  • c is the child
add Used to specify an alternative for adding children to the collection. Optional. Useful when a modifiable collection is not accessible. A method name. The method must accept two Object argument values for the key and value, in that order. n/a n/a A Closure of the form
  • {p, k, c -> ...}
  • {p, c -> ...}
where
  • p is the parent
  • k is the key
  • c is the child
Note, if the first Closure form is used, then the property key must be specfied. By using the second form, the Closure is responsible for determining and using the correct key for the child.
property Used to identify or modify the actual property. Optional. The default is to set the property using the node's name. A property or field name. n/a n/a A Closure of the form
  • {o, v -> ...}
  • where
    • o is the object
    • v is the value
min (property) Used to specify the minimum property size. Optional. The default is no minimum. The size of a property is property dependent: A Comparable type, such as Integer or Double. n/a n/a n/a
max (property) Used to specify the maximum property size. Optional. The default is no maximum. See min (property) above. A Comparable type, such as Integer or Double. n/a n/a n/a
req Used to specify if a property must be specified. Optional. n/a true or false n/a n/a
def (property) Used to specify a default value. Optional. Any literal value may be passed to the property. Any object may be passed to the property. Any Class is passed like an object. A Closure returning a result of the form:
  • {-> ...}
The Closure is called each time a default value is needed.
def (collection) Used to specify a default collection. Optional. Any literal may be specified for non-map collections. If a Collection is specified, its values are added individually to the collection. Any other object is simply added to the collection. n/a n/a

Inheriting and Extending Schemas

By using the schema property, your schemas can inherit and extend from other schemas. This can be a powerful technique and allows you to reuse schemas and even create recursive models. For example:
  MetaBuilder mb = new MetaBuilder()
  def parentDef = mb.define {
      parent(factory: TestParent) {
          properties {
              name(req: true)
          }
          collections {
              listOfChildren {
                  child(schema: 'parent') {
                      properties {
                          name(req: false)  // would have been true without this
                      }
                  }
              }
          }
      }
  }
 
The above example also shows how a sub-schema can override the property settings of its super-schema.

Version:
$Id: MetaBuilder.java 62 2009-07-28 07:32:10Z didge $
Author:
didge
See Also:
ObjectGraphBuilder

Nested Class Summary
protected static class MetaBuilder.DefaultBuildSchemaNodeFactory
          Default SchemaNode factory used when build(groovy.lang.Closure, groovy.lang.Closure) is called.
protected static class MetaBuilder.DefaultCollectionSchemaNodeFactory
          Default CollectionSchemaNode factory used when define(groovy.lang.Closure) is called.
protected static class MetaBuilder.DefaultDefineSchemaNodeFactory
          Default SchemaNode factory used when define(groovy.lang.Closure) is called.
static class MetaBuilder.FactoryInterceptorMetaClass
          Supports builder scripts by dispatching methods against MetaObjectGraphBuilder.
protected static class MetaBuilder.ListBuilder
           
protected  class MetaBuilder.SchemaAdder
           
 
Constructor Summary
MetaBuilder()
          Constructs a MetaBuilder with the default meta schema, node factory and class loader.
MetaBuilder(ClassLoader classLoader)
          Constructs a MetaBuilder with the default meta schema, node factory and specified class loader.
MetaBuilder(SchemaNode defaultMetaSchema, ClassLoader classLoader)
          Constructs a MetaBuilder with the given default meta schema
 
Method Summary
 void addSchema(String name, Object schema)
          Adds a previously defined schema with the given name.
 Object build(Class viewClass)
           
 Object build(Closure c)
           
 Object build(Closure objectVisitor, Class viewClass)
          Creates a Script from viewClass and returns the last object built by running the resulting script.
 Object build(Closure objectVisitor, Closure c)
           
 Object build(Closure objectVisitor, Script script)
           
 Object build(Closure objectVisitor, URL url)
           
 Object build(Script script)
           
 Object build(URL url)
           
 List buildList(Class viewClass)
           
 List buildList(Closure c)
           
 List buildList(Script script)
           
 List buildList(URL url)
           
static RuntimeException createClassNameNotFoundException(String name)
           
static RuntimeException createCollectionException(String name, String error)
           
static RuntimeException createCollectionException(String name, Throwable error)
           
protected  SchemaNode createDefaultMetaSchema()
          The default implementantion returns the MetaBuilder meta schema: Subclasses may override this method to implement their own default meta schemas as needed.
static RuntimeException createFactoryException(String name, String error)
           
static RuntimeException createFactoryException(String name, Throwable error)
           
protected  MetaObjectGraphBuilder createMetaObjectGraphBuilder(SchemaNode defaultSchema, Factory defaultNodeFactory, Closure objectVisitor)
          Returns a new MetaObjectGraphBuilder with the given default schema and node factory
static RuntimeException createNodeException(String name, String error)
           
static RuntimeException createNodeException(String name, Throwable error)
           
static RuntimeException createPropertyException(String name, String error)
           
static RuntimeException createPropertyException(String name, Throwable error)
           
static RuntimeException createSchemaNotFoundException(String name)
           
 Object define(Class viewClass)
           
 Object define(Closure c)
          Defines, registers and returns a new schema using the default meta schema.
 Object define(Script script)
           
 Object define(URL url)
           
 ClassLoader getClassLoader()
          Returns the class loader in use by the MetaBuilder.
 Factory getDefaultBuildNodeFactory()
           
 Factory getDefaultDefineNodeFactory()
           
 SchemaNode getDefaultMetaSchema()
          Returns the default schema.
 SchemaNode getSchema(String name)
          Returns a previously defined schema with the given name.
 void setClassLoader(ClassLoader classLoader)
          Sets the ClassLoader to use by the MetaBuilder.
 void setDefaultBuildNodeFactory(Factory defaultBuildNodeFactory)
           
 void setDefaultDefineNodeFactory(Factory defaultDefineNodeFactory)
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

MetaBuilder

public MetaBuilder()
Constructs a MetaBuilder with the default meta schema, node factory and class loader.

See Also:
createDefaultMetaSchema()

MetaBuilder

public MetaBuilder(ClassLoader classLoader)
Constructs a MetaBuilder with the default meta schema, node factory and specified class loader.

Parameters:
classLoader -
See Also:
createDefaultMetaSchema()

MetaBuilder

public MetaBuilder(SchemaNode defaultMetaSchema,
                   ClassLoader classLoader)
Constructs a MetaBuilder with the given default meta schema

Parameters:
defaultMetaSchema - the default schema
Method Detail

getDefaultBuildNodeFactory

public Factory getDefaultBuildNodeFactory()

setDefaultBuildNodeFactory

public void setDefaultBuildNodeFactory(Factory defaultBuildNodeFactory)

getDefaultDefineNodeFactory

public Factory getDefaultDefineNodeFactory()

setDefaultDefineNodeFactory

public void setDefaultDefineNodeFactory(Factory defaultDefineNodeFactory)

createDefaultMetaSchema

protected SchemaNode createDefaultMetaSchema()
The default implementantion returns the MetaBuilder meta schema: Subclasses may override this method to implement their own default meta schemas as needed.

Returns:
see above

define

public Object define(Closure c)
Defines, registers and returns a new schema using the default meta schema. Defined schemas are available for use in building new objects on the MetaBuilder directly.

Parameters:
c -
Returns:
see above

define

public Object define(Class viewClass)

define

public Object define(Script script)

define

public Object define(URL url)
              throws IOException
Throws:
IOException

build

public Object build(Closure objectVisitor,
                    Closure c)

build

public Object build(Closure c)

buildList

public List buildList(Closure c)

build

public Object build(Class viewClass)

build

public Object build(Closure objectVisitor,
                    Class viewClass)
Creates a Script from viewClass and returns the last object built by running the resulting script.

Parameters:
objectVisitor - a Closure that must accept two arguments: the node name and the node
viewClass -
Returns:
see above

buildList

public List buildList(Class viewClass)

build

public Object build(URL url)
             throws IOException
Throws:
IOException

build

public Object build(Closure objectVisitor,
                    URL url)
             throws IOException
Throws:
IOException

buildList

public List buildList(URL url)
               throws IOException
Throws:
IOException

build

public Object build(Script script)

build

public Object build(Closure objectVisitor,
                    Script script)

buildList

public List buildList(Script script)

getSchema

public SchemaNode getSchema(String name)
Returns a previously defined schema with the given name.

Parameters:
name - see above
Returns:
see above

addSchema

public void addSchema(String name,
                      Object schema)
Adds a previously defined schema with the given name.

Parameters:
name - see above
schema - see above

getClassLoader

public ClassLoader getClassLoader()
Returns the class loader in use by the MetaBuilder.

Returns:
see above

getDefaultMetaSchema

public SchemaNode getDefaultMetaSchema()
Returns the default schema.

Returns:
see above

createMetaObjectGraphBuilder

protected MetaObjectGraphBuilder createMetaObjectGraphBuilder(SchemaNode defaultSchema,
                                                              Factory defaultNodeFactory,
                                                              Closure objectVisitor)
Returns a new MetaObjectGraphBuilder with the given default schema and node factory

Parameters:
defaultSchema -
defaultNodeFactory -
Returns:
see above

setClassLoader

public void setClassLoader(ClassLoader classLoader)
Sets the ClassLoader to use by the MetaBuilder. It is sometimes necessary, especially in Groovy scripts, to provide ClassLoader explicity to resolve classes by name.

Parameters:
classLoader - the ClassLoader to use

createNodeException

public static RuntimeException createNodeException(String name,
                                                   String error)

createNodeException

public static RuntimeException createNodeException(String name,
                                                   Throwable error)

createPropertyException

public static RuntimeException createPropertyException(String name,
                                                       String error)

createPropertyException

public static RuntimeException createPropertyException(String name,
                                                       Throwable error)

createCollectionException

public static RuntimeException createCollectionException(String name,
                                                         String error)

createCollectionException

public static RuntimeException createCollectionException(String name,
                                                         Throwable error)

createFactoryException

public static RuntimeException createFactoryException(String name,
                                                      String error)

createFactoryException

public static RuntimeException createFactoryException(String name,
                                                      Throwable error)

createSchemaNotFoundException

public static RuntimeException createSchemaNotFoundException(String name)

createClassNameNotFoundException

public static RuntimeException createClassNameNotFoundException(String name)


Copyright © 2008 FoundryLogic, LLC. All Rights Reserved.