public class XMLParamProcessor
extends java.lang.Object
Utility to create Java Objects from xml. Recursively creates or retrieves objects from symbol table
for constructor and method parameters. With some helper classes inserted into the symbol table beforehand,
can be pretty much used to execute arbitrary Java code. Normally parameters to class constructors are
parsed recursively from the child elements of the creating element. Your class can however implement
XMLParamAware
in which case your class will be provided with the DOM element and you can implement custom
parameter parsing. XMLParamAware
clasesses are also given this XMLParamProcessor
so they have access to the
entire symbol table created (at the time of their generation). So parameters can also be passed by putting objects
in the symbol table with specific keys. This is especially usefull for objects that are passed to allmost
every object (such as loggers; which many classes will try to get from symbol table with key "logger").
New objects are usually created by providing the full class name of the created object. You can also map element names to different classes beforehand and then create new objects with these element names.
Only one of the idref, class, array and static attributes can be specified. This determines how to create or retrieve the object. The value of idref must be the id of the object in the symbol table, the value of the other three must be a full class name. With idref you can use either method or field attribute to invoke a method or get the value of a field respectively and with static you must use one of these.
When you use class attribute to create a new object, note that the class you are creating might implement XMLParamAware, in which case refer to the documentation of that class about how the child elements are used. You must use either method or field attribute when using static.
For example, consider the following xml:
<object id="p" class="Store">
<param class="java.lang.String" literal="true">Store name</param>
<param array="StoreItem">
<item class="StoreItem">
<param class="java.lang.String" literal="true">apple</param>
<param class="java.lang.Integer" literal="true">5</param>
</item>
<item class="StoreItem">
<String>banana</String>
<Integer>10</Integer>
</item>
</param>
</object>
<object id="customer" class="Customer"/>
<method id="error" idref="p" method="buyOne">
<param idref="customer"/>
<param class="java.lang.String">apple</param>
</method>
This would roughly be equivalent to the following java code:
Note that the first StoreItem is created using the full syntax and the second item shows how to use the
shorter syntax for java.lang.* classes.
Store p=new Store("Store name",new StoreItem[]{new StoreItem("apple",5),new StoreItem("banana",10)});
Customer customer=new Customer();
Boolean error=p.buyOne(customer,"apple");
As another example, the following is pretty much equal to System.out.println("Hello World");
(note the use of
name space).
<root xmlns:xp="http://wandora.org/xmlparamprocessor">
<object xp:id="out" xp:static="java.lang.System" xp:field="out"/>
<method xp:idref="out" xp:method="println">
<param xp:class="java.lang.String" xp:literal="true">Hello World!</param>
</method>
</root>
Note the autoboxing/unboxing of primitive types. However, the symbol table will only contain Objects, that is no primitive types. Also note that String,Integer,Double,Boolean etc all have a constructor accepting a single String parameter thus the creation of Integers with literal attribute set to true works (as does the shorter syntax using Integer element name). Note that arithmetic operations are not directly possible. However you could make an object into the symbol table which provides the necessary methods.
To use XMLParamProcessor
, first create a new instance of it.
Then add whatever objects you want to the symbol table (optional).
Then use processElement
or one of the create methods to process elements of the XML.
Finally you can get objects from the symbol table if you need to.
You can use getObjectType to get the element name used to create the object. This way you can easily group your objects into different categories.
Note that by default XMLParamProcessor
uses a namespace "http://wandora.org/xmlparamprocessor" for
all the attributes. So either use setNameSpace method to set the name space to null to disable this or take
care that your xml has proper name spaces setup and that the xml implementation supports name spaces.
You should use javax.xml.parsers.DocumentBuilderFactory.setNamespaceAware(true) before creating the
document builder used to parse the document.
XMLParamAware
Modifier and Type | Field and Description |
---|---|
private java.util.HashMap |
classMap |
static java.lang.String |
DEFAULT_NAMESPACE
The default namespace URI.
|
private java.util.HashSet |
forcedLiterals |
private java.lang.String |
nameSpace |
private java.util.HashMap |
objectTable |
private java.util.HashMap |
objectTypeTable |
Constructor and Description |
---|
XMLParamProcessor()
Creates a new instance of XMLParamProcessor
|
Modifier and Type | Method and Description |
---|---|
void |
addObjectToTable(java.lang.String id,
java.lang.Object o)
Adds (or reassigns) a single object to the symbol table.
|
java.lang.Object[] |
createArray(org.w3c.dom.Element e,
java.lang.Object[] arrayType)
Creates an array of the child nodes of the given element.
|
java.lang.Object |
createObject(org.w3c.dom.Element e)
Interprets one element and returns the created or retrieved object.
|
java.lang.Object |
createObject(org.w3c.dom.Element e,
java.lang.String forceClass) |
static java.lang.reflect.Constructor |
findConstructor(java.lang.Class cls,
java.lang.Object[] params) |
static java.lang.reflect.Method |
findMethod(java.lang.Class cls,
java.lang.String method,
java.lang.Object[] params) |
private java.lang.String |
getAttribute(org.w3c.dom.Element e,
java.lang.String attr) |
java.lang.String |
getClassMapping(java.lang.String nodeName) |
static java.lang.String |
getElementContents(org.w3c.dom.Element e) |
static java.lang.String |
getNodeContents(org.w3c.dom.Node n) |
java.lang.Object |
getObject(java.lang.String id)
Gets an object from the symbol table.
|
java.lang.String |
getObjectType(java.lang.String id) |
java.util.HashMap |
getSymbolTable()
Returns the whole symbol table.
|
static java.lang.Class[] |
getTypeArray(java.lang.Object[] params) |
static boolean |
isInstanceOrBoxed(java.lang.Class type,
java.lang.Object param) |
static void |
main(java.lang.String[] args)
A test main method.
|
void |
mapClass(java.lang.String nodeName,
java.lang.String className)
Map a given node name to a specific class.
|
static org.w3c.dom.Document |
parseDocument(java.io.InputStream in)
A convenience method to parse a Document from a File.
|
static org.w3c.dom.Document |
parseDocument(java.lang.String file)
A convenience method to parse a Document from a File.
|
java.lang.Object |
processElement(org.w3c.dom.Element e)
Processes all the child elements of the given element.
|
void |
setNameSpace(java.lang.String ns)
Sets the used name space URI.
|
void |
setSymbolTable(java.util.HashMap table)
Reset the whole symbol table.
|
public static final java.lang.String DEFAULT_NAMESPACE
private java.util.HashMap objectTable
private java.util.HashMap objectTypeTable
private java.lang.String nameSpace
private java.util.HashMap classMap
private java.util.HashSet forcedLiterals
public XMLParamProcessor()
public void setNameSpace(java.lang.String ns)
ns
- The new name space URI or null to disable the use of name spaces.public void setSymbolTable(java.util.HashMap table)
table
- The new symbol table. Should contain id Strings mapped to the corresponding objects.public void mapClass(java.lang.String nodeName, java.lang.String className)
public java.lang.String getClassMapping(java.lang.String nodeName)
public void addObjectToTable(java.lang.String id, java.lang.Object o)
id
- The id of the object.o
- The object to be assigned with the given id.public java.lang.Object getObject(java.lang.String id)
id
- The id of the object to get.public java.lang.String getObjectType(java.lang.String id)
public java.util.HashMap getSymbolTable()
public static java.lang.Class[] getTypeArray(java.lang.Object[] params)
public static boolean isInstanceOrBoxed(java.lang.Class type, java.lang.Object param)
public static java.lang.reflect.Constructor findConstructor(java.lang.Class cls, java.lang.Object[] params) throws java.lang.Exception
java.lang.Exception
public static java.lang.reflect.Method findMethod(java.lang.Class cls, java.lang.String method, java.lang.Object[] params) throws java.lang.Exception
java.lang.Exception
private java.lang.String getAttribute(org.w3c.dom.Element e, java.lang.String attr)
public static java.lang.String getNodeContents(org.w3c.dom.Node n)
public static java.lang.String getElementContents(org.w3c.dom.Element e)
public java.lang.Object createObject(org.w3c.dom.Element e) throws java.lang.Exception
e
- The element to interpret.java.lang.Exception
public java.lang.Object createObject(org.w3c.dom.Element e, java.lang.String forceClass) throws java.lang.Exception
java.lang.Exception
public java.lang.Object[] createArray(org.w3c.dom.Element e, java.lang.Object[] arrayType) throws java.lang.Exception
e
- The element whose child elements are parsed.arrayType
- An object used to determine the type of the returned array. If null, the returned
array will be of type Object[].java.lang.Exception
public java.lang.Object processElement(org.w3c.dom.Element e) throws java.lang.Exception
e
- The element whose child elements are parsed.java.lang.Exception
public static org.w3c.dom.Document parseDocument(java.lang.String file) throws java.lang.Exception
java.lang.Exception
public static org.w3c.dom.Document parseDocument(java.io.InputStream in) throws java.lang.Exception
java.lang.Exception
public static void main(java.lang.String[] args) throws java.lang.Exception
java.lang.Exception
Copyright 2004-2015 Wandora Team