public class Mapper<T>
extends java.lang.Object
GenericSAXHandler
for binding low level
XML data to Java objects; this is the base class containing the main logic
responsible for that. Normally users of GenericSAXHandler
define a custom Mapper
subclass.
The default behavior provided by Mapper
base class is to
attempt to relate XML attributes to setter methods in the Java class, on a
best effort basis, following the Java bean conventions. Attempts are made
to convert String
attribute values read from XML to the
respective properties' own types. In cases where this default approach does
not work, a custom property setter can be defined by Mapper
subclasses, overriding the one in the base (setProperty(Object, String, String)
).
As the nested structure of XML nodes reflect the composite nature of Java
objects, mappers also have the duty of controlling how objects that spring
from a certain sub-tree of the XML document are "consumed" by the parent
object, corresponding to its ancestor node in the XML tree. Unlike setting
properties, no assumptions can be made here regarding how an object is to
be integrated in its container, therefore the Mapper
subclass
for the parent object would have to override method mergeSubObj(
Object, Object)
.
Recursive composite structures (types that contain instances of their own
type in the object structure) are supported by mappers by default. The same
mapper instance can be used simultaneously with any number of objects in
process of being constructed at a given time and subclasses can learn about
the context where they're operating by using the convenience methods
provided by this Mapper
base class (getXmlPath()
,
getParentTag()
).
Mapping XML nodes to Java types is also sensitive to context. The same XML tag can be mapped to different types, depending on where in the XML tree it appears. If a mapper is installed for a more specific context (e.g. "cfg/schema/namespace/dialect-specific/parameter") it takes precedence over the general purpose mapper installed for the simple tag name (in this case "parameter").
Constraints can be added for data that is read from XML: for any element,
sets of mandatory and optional attributes as well as required and optional
child elements can be specified with setConstraints(String[],
String[], String[], String[])
.
Check the documentation in GenericSAXHandler
for more details
on how mappers are used.
This class is not synchronized.
GenericSAXHandler
Modifier and Type | Field and Description |
---|---|
private java.lang.Class<T> |
cls
The type of the Java object produced by this mapper.
|
(package private) java.util.Set<java.lang.String> |
optionalAttrs
Optional attributes for XML nodes handled by this mapper.
|
(package private) java.util.Set<java.lang.String> |
optionalChld
Optional child elements for XML nodes handled by this mapper.
|
(package private) java.util.Set<java.lang.String> |
requiredAttrs
Mandatory attributes for XML nodes handled by this mapper.
|
(package private) java.util.Set<java.lang.String> |
requiredChld
Mandatory child elements for XML nodes handled by this mapper.
|
private java.lang.String |
xmlPath
The path made of all XML elements (both handled and not handled by
mappers) from root up to and including the current node, processed by
this mapper.
|
Constructor and Description |
---|
Mapper(java.lang.Class<T> c)
Constructs a
Mapper instance that is able to build and
populate Java objects of a given type. |
Modifier and Type | Method and Description |
---|---|
protected void |
applyAttributes(org.xml.sax.Attributes attrs,
T payloadObj)
Applies a set of XML attributes as properties into the Java object
produced by this mapper.
|
static java.lang.String |
cap1st(java.lang.String s)
Utility method for string capitalizing (first character to upper case).
|
protected void |
checkSubObjType(java.lang.Object o,
java.lang.Class<?> c)
Utility method for checking that the type of an object is (a subtype
of) a given class.
|
protected void |
checkSubObjTypes(java.lang.Object o,
java.lang.Class<?>[] clsTab)
Check that the given (child) object is of one of the supplied types.
|
protected void |
checkUnexpectedChild(java.lang.String chld)
Checks if a child element can appear within the node processed by
this mapper: if constraints are active (defined) and the child is
neither mandatory nor optional, a
ConfigurationException
is thrown. |
(package private) GenericSAXHandler.ActiveNode<T> |
createActiveNode(java.lang.String mapperKey)
Creates generic
ActiveNode containers, holding the properly
typed newly created Java object together with the correct Mapper
that is going to be used for populating it. |
protected T |
createPayloadObj()
Default factory method for creating the Java object that this mapper
will populate with data from XML.
|
private void |
genSet(java.lang.Object o,
java.lang.String n,
java.lang.String v)
Generic property setter, following java bean conventions.
|
protected java.lang.String |
getParentTag()
Provides the name of the parent XML tag.
|
protected java.lang.Class<T> |
getType()
Gives the Java type of objects that this mapper is capable of
building.
|
protected java.lang.String |
getXmlPath()
Getter for the path to (and including) the XML node handled by this
mapper.
|
protected void |
mergeSubObj(T p,
java.lang.Object c)
To be overridden in subclasses if the object built by this mapper has
a composite structure and needs to "consume" sub-objects.
|
protected void |
setConstraints(java.lang.String[] reqAttrs,
java.lang.String[] optAttrs,
java.lang.String[] reqChld,
java.lang.String[] optChld)
Adds constraints for the kind of XML nodes handled by this particular
mapper, in the form of mandatory and optional sets of attributes
and/or child elements.
|
protected void |
setProperty(T p,
java.lang.String n,
java.lang.String v)
By default we use the bean convention to fill in object properties.
|
(package private) void |
setXmlPath(java.lang.String path)
Updates the path to (and including) the XML node handled by this mapper.
|
private java.lang.Class<T> cls
java.util.Set<java.lang.String> requiredAttrs
null
, the constraint is disabled. By default this is
set to null
.java.util.Set<java.lang.String> optionalAttrs
null
the constraint is disabled and any attributes are
allowed to occur. By default this is initialized to null
.java.util.Set<java.lang.String> requiredChld
null
, the constraint is disabled. By default this
is set to null
.java.util.Set<java.lang.String> optionalChld
null
the constraint is disabled and any children are
allowed to occur. By default this is initialized to null
.private java.lang.String xmlPath
GenericSAXHandler.XMLPATH_SEPARATOR
as separator, defined to '/'.
This information is not important for the logic in this mapper base class itself (it's only used in error reporting), but may be useful to subclasses as context information.
getParentTag()
public Mapper(java.lang.Class<T> c) throws java.lang.IllegalArgumentException
Mapper
instance that is able to build and
populate Java objects of a given type.c
- The Java type of the object constructed and populated by
this mapper.java.lang.IllegalArgumentException
- If no class object is given.public static java.lang.String cap1st(java.lang.String s)
s
- String to be capitalized.s
.protected final void setConstraints(java.lang.String[] reqAttrs, java.lang.String[] optAttrs, java.lang.String[] reqChld, java.lang.String[] optChld)
null
value:
If the set of mandatory attributes/children is empty or null
, the respective constraint is disabled: there are no required
attributes or child elements, respectively. The meaning for the sets
of optional items is different: null
means the
constraint is disabled (any elements can appear), while the empty set
indicates that there are no optional elements.
reqAttrs
- Array containing mandatory attribute names.optAttrs
- Array containing optional attribute names.reqChld
- Array containing mandatory child names.optChld
- Array containing optional attribute names.protected final void checkUnexpectedChild(java.lang.String chld) throws ConfigurationException
ConfigurationException
is thrown.chld
- The name of the XML child element that is being checked.ConfigurationException
- If the child is unexpected.protected T createPayloadObj() throws java.lang.IllegalStateException
java.lang.IllegalStateException
- If the default (no-arg) constructor could not be invoked
successfully.protected final void checkSubObjType(java.lang.Object o, java.lang.Class<?> c) throws java.lang.IllegalArgumentException
IllegalArgumentException
is thrown
if this is not the case.
This method meant to be used in subclasses for validation of child (sub-objects) that are to be consumed by the object handled by this mapper.
o
- The object to be checked.c
- The type that the object is to be checked against.java.lang.IllegalArgumentException
- If the object is not an instance of the given type or any of
its subtypes.protected final void checkSubObjTypes(java.lang.Object o, java.lang.Class<?>[] clsTab) throws java.lang.IllegalArgumentException
checkSubObjType(Object, Class)
.o
- The object to be checked.clsTab
- The types that the object is to be checked against.java.lang.IllegalArgumentException
protected void setProperty(T p, java.lang.String n, java.lang.String v) throws java.lang.IllegalStateException
p
- The target instance where the property will be set.n
- The name of the property, following the Java bean convention.v
- The string representation of property's value, as it was read
from XML.java.lang.IllegalStateException
protected final void applyAttributes(org.xml.sax.Attributes attrs, T payloadObj) throws ConfigurationException, java.lang.IllegalStateException
attrs
- The set of attributes, as they were picked from the XML node
by the SAX parser.ConfigurationException
- If unexpected attributes are encountered, as dictated by the
respective constraint, if active.java.lang.IllegalStateException
protected final java.lang.Class<T> getType()
protected void mergeSubObj(T p, java.lang.Object c)
Mapper
subclasses
must provide.p
- The current (parent) object that will consume the sub-object.c
- The child (sub-object) that will be consumed by this mapper's
object.protected final java.lang.String getXmlPath()
GenericSAXHandler.XMLPATH_SEPARATOR
as a separator (defined to '/').String
.protected java.lang.String getParentTag()
Mapper
base class, it's given here only as a
convenience method that may come handy as context information in
subclasses for knowing the where we are in the XML tree / object graph.null
if no parent tag exists.getXmlPath()
final void setXmlPath(java.lang.String path)
GenericSAXHandler.XMLPATH_SEPARATOR
as a
separator (defined to '/').path
- The XML path.final GenericSAXHandler.ActiveNode<T> createActiveNode(java.lang.String mapperKey)
ActiveNode
containers, holding the properly
typed newly created Java object together with the correct Mapper
that is going to be used for populating it.mapperKey
- The key that the mapper was installed for (usually an XML tag
name, but can also be a complete path in the XML tree, using
GenericSAXHandler.XMLPATH_SEPARATOR
as separator,
defined to '/').ActiveNode
instance containing the mapper object
together with a newly created payload object that will be
populated by the mapper.private void genSet(java.lang.Object o, java.lang.String n, java.lang.String v) throws java.lang.IllegalStateException
o
- The target object where the property will be set.n
- The name of the property to be set.v
- The string representation of property's value.java.lang.IllegalStateException
- If a suitable setter for the given property could not be
found or invoked successfully.