Requirements
Definitions
- Attribute
- An attribute of an element in an XML document. Note that attributes in Java objects are referred to as properties, since they can only be read and changed via getters and setters
- Converter
- A converter is a pair of methods, one of which takes a String and parses it into a primative or object and another method which takes a primative or object and creates a string representation.
- Element
- A node in an XML document.
- Object
- An instance of a Java class.
- Property
- A getter and a setter method which, respectively, reads and changes an underlying attribute in Java object.
- Tag
- A node in an XML document. Synonymous with Element.
Requirements
Reading XML
- Parse data from XML into a single root object.
- Properties in objects which are primatives or which are objects that map directly to primatives will be converted from a String to the appropriate property type and the setter for that property will be called.
- Properties in objects which have complex object types (rather than primatives or objects that map directly to primatives) will cause other objects to be created. Those objects are then passed to the setter method for that property.
- There will be no limit on how deep the object graph representing the XML can be.
- XML attributes are processed as if they where elements. For example, <User name="foo"/> is functionally the same as <User><name>foo</name></User>
- Objects are instantiated by an ObjectFactory class. The default implementation of the
ObjectFactory tries to create an object instance by calling a
static getInstance()method on the object before tryingClass.forName().newInstance() - If XML tags are duplicated at the same level in the XML, setters should be implemented
such that they add to a collection. For example, if a Stock object contains float values
representing price bids, the setter
setBid(float bid)should actually add the float to a List of bids{ bids.add(bid); } - Elements/attributes in the XML file can automatically be matched with objects and properties.
- A 'setter' method can start either with the word 'set' or the word 'add'. Either setAttribute or addAttribute would be called by the framework when parsing XML and coming across an <attribute> tag.
- Names of elements and attributes are mapped directly to property setters in an
object, with a direct match between element name and property being assumed. For
example, <someText>foobar</someText> would mean that the
setSomeText()method (oraddSomeText()) would be called. - A setter can use the name of an Object's immediate super class instead
of the name of the object as part of the setter. For example, if you had
a
SalesLotobject which contained a list of all vehicles for sale, and you had three types of vehicles,Car,MotorbikeandBoatthat extended aVehicleclass, theSalesLotcould have aaddVehicle()method and all <Car>, <Motorbike> and <Boat> objects would be added to theSalesLotinstance through theaddVehicle()method. - Elements/attributes in the XML file can optionally be matched to objects/properties of any name using mappings.
- Objects can be mapped from an xml tag/attribute name to a Java ojbect name.
- Properties of an object can be mapped from a specific tag/attribute name to a given Java property name, for that specific object.
- Properties can also be mapped from a tag/attribute name to a specific Java name on a global basis, so that those properties in ALL Java objects will get renamed.
- Java classes in different packages but with the same name will be supported.
- Elements which represent classes can use the fully qualified classname as
element names. For example, the tags <com.foo.Cheese> <com.bar.Cheese>
in XML will create two different kinds of
Cheeseobjects (from the packagescom.fooandcom.bar). - Tag names differentiated by a different namespace can be individually
associated with a specific class by mapping the namespaces to specific
packages. One might have the namespace urn:foobar-com-user mapped to
the package
com.foobar.userand the namespace urn:foobar-com-consumer mapped to the packagecom.foobar.consumerso that you can differentiate User objects found in both packages. - A
Converterwill parse the XML string data and convert it into a specific type of object. - Converters are defined for a specific Java data type (long, java.lang.Interger, java.util.Date, etc).
- A converter can optionally be associated with a specific property of a specific object by specifying the
Converterin thePropertyMap. Writing XML
- Take a single root object and serialize it to a string of XML.
- Properties of the object which are primatives or which are objects that map directly to primatives will be serialized to a String and added to the XML.
- Properties of the object which are complex objects (rather than primatives or objects
that map directly to primatives) will actually generate a sub-element in the XML. The
properties of that complex object will then be serialized inside of the sub-element.
For example, if you have an object called
Studentwhich has a property that is another object calledTeacher, a Teacher node will be created inside the Student node in the resulting XML. - There will be no limit on how deep the object graph of the root object will be. All complex objects will be traversed and their primative properties will be serialized to the XML.
- Properties which return a
Listwill actually be written out as a series of XML tags with the same name, existing at the same level in the XML hierarchy. For instance, a list offloatprimatives which indicate bid prices for the gettergetBidwould be serialized like:
<Stock><name>foo</name><bid>1.23</bid><bid>1.25</bid><bid>1.33</bid></Stock>- Note, at the moment, you should name getters that return a List with a name that is singular, not plural (as in the getBid() example above). More specifically, the property name of the getter must match the property name of the setter.
- Java object and property names, by default, will become the tag names used in the XML. Property names are derrived from the 'getter' methods of the Java object.
- A 'getter' method can start with either the word 'get' or the word 'is'. Either
getAttributeorisAttributewould be called by the framework when generating XML. A getter that starts with 'is' does not have to return a boolean, though by convension it should. - If the getter method returns a primative or an object that maps directly to a
primative, the property name portion of the getter name will become the XML tag
(with the first letter converted to lower case). For example,
float getBid()will use the tag <bid>.Integer getNumberOfMileswill use the tag <numberOfMiles>. - If the getter method returns a complex object, it is the the class name of the
complex object which is used as the tag name. Note, you must set the
includePackageNameflag in XmlWriter to true if you want the class' fully qualified classname to be used (otherwise the package name is omitted). - By default, objects and their properties are written out to XML elements. It is possible to specify on a property by property basis that a given property should be output as an XML attribute, rather than as an element.
- The
PropertyMapobject has awriteAsAttributeboolean flag which controls whether that property is written as an attribute or as an element. - By default the
writeAsAttributeflag is false - The
writeAsAttributeflag can be controlled either programatically or through an XML configuration file (see Configuring the Framework below). - The property to be written must have a converter defined for its type.
- The property cannot be a List or an array.
- The property cannot have a null value.
- Java object/property names can optionally be associated with arbitrary XML tag/attribute names.
- Objects can be mapped to any tag name desired on an object by object basis
- Properties of a specific object can be mapped to a specific tag name on a per property basis for a specific object
- Properties can also be mapped to specific tag name regardless of which object they are found in using a 'global' property mapping
- You can specify a namespace mapping for Java packages so that Objects with the same name in different packages can be properly unmarshalled from the XML later. A namespace mapping will define a namespace URI and a prefix to use in the XML tag names for a give package.
- A
Converterwill convert a value from a getter to XML string data. - Converters are defined for a specific Java data type (long, java.lang.Interger, java.util.Date, etc).
- A converter can optionally be associated with a specific property of a specific object by specifying the
Converterin thePropertyMap. Configuring the Framework
- The framework can be configured programatically by manipulating the 'singleton' XmlIOConfig
object or by creating an instance of XmlIOConfig before you create an XmlReader or XmlWriter object.
For instance:
XmlIOConfig config = XmlIOConfig.getInstance(); config.addConverter(...); config.addNamespaceMap(...); XmlWriter writer = new XmlWriter(...); ...
- The framework can be configured using an XML file which will define converters, XML tag/Java object mappings, XML attribute/Java setter mappings, and namespace/package name mappings.
Extending the Framework
- Converters are defined for specific fully qualified classnames. To create a converter for com.company.Foo, the converter's type would be "com.company.Foo".
- Each converter currently needs two methods, both of which must be in the same class.
- The method which takes a string and returns an instance of the given class should start with parse (ie,
parseString()). - The method which takes an object and returns a string representation should start with print (ie,
printString()).
The framework will parse XML and create an object graph representing the elements and attributes found.
The framework will write an object and all it's (javabean-like) properties, including complex data types, to String of XML.
The framework will configure itself with some basic, useful options to begin with, but can be overridden and/or extended.
You can currently extend the framework by replacing existing converters or by adding your own.