Package javolution37.javolution.xml
XML; and the complementary reconstruction of the
object graph from XML.See: Description
-
Class Summary Class Description CharacterData This class represents a text that is not markup and constitutes the "Character Data" of a XML document.ObjectReader<T> This class restores objects which have been serialized in XML format using anObjectWriter.ObjectWriter<T> This class takes an object and formats it to XML (SAX2 events or stream).XmlElement This class represents a XML element.XmlFormat<T> This class represents the format base class for XML serialization and deserialization.XmlInputStream<T> This class represents an object input stream usingObjectReaderfor object deserialization.XmlOutputStream<T> This class represents an object output stream usingObjectWriterfor object serialization. -
Exception Summary Exception Description XmlException Signals that a problem of some sort has occurred when serializing/deserializaing an object from its XML representation.
Package javolution37.javolution.xml Description
Provides support for the encoding of objects, and the objects reachable from them,
into XML; and the complementary reconstruction of the
object graph from XML.
XML marshalling/unmarshalling facility:
Key Advantages:
- Very fast and small memory footprint (unmarshalling performed using
our real-time
pull parser). - Performance on a par or better than default JavaTM Serialization/Deserialization (See bindmark for performance comparison).
- Runs on any platform including J2ME CLDC 1.0 It does not require reflection or
or any interface (e.g.
Serializable) to be implemented. - The XML mapping can be defined for a top class (or interface) and is automatically inherited by all sub-classes (or all implementing classes).
- Allows for sharing and unicity (through the use of factory methods instead of constructors).
- Supports document cross-references (to avoid expanding objects already formatted).
- The XML mapping is customizable and is not tight to the class internal representation (e.g. impervious to obfuscation). It can also be used with xml data produced by other products.
- The XML mapping can be dynamically changed at run-time.
- Integrated with NIO high-performance framework (e.g.
java.nio.ByteBuffer). -
XML formatscan be generated from the source code using the JavoClipse Eclipse plug-in (see Javolution Tools).
The default XML mapping for a class and its sub-classes is typically defined using
a static final XmlFormat instance.
For example:
Sub-classes may override the inherited XML format:
public abstract class Graphic {
private boolean _isVisible;
private Paint _paint; // null if none.
private Stroke _stroke; // null if none.
private Transform _transform; // null if none.
// XML format with name associations (members identified by an unique name).
// See XmlFormat for examples of positional associations.
protected static final XmlFormat<Graphic> XML = new XmlFormat<Graphic>(Graphic.class) {
public void format(Graphic g, XmlElement xml) {
xml.setAttribute("isVisible", g._isVisible);
xml.add(g._paint, "Paint");
xml.add(g._stroke, "Stroke");
xml.add(g._transform, "Transform");
}
public Graphic parse(XmlElement xml) {
Graphic g = xml.object();
g._isVisible = xml.getAttribute("isVisible", true);
g._paint = xml.get("Paint");
g._stroke = xml.get("Stroke");
g._transform = xml.get("Transform");
return g;
}
};
}
The following writes a graphic area to a file, then reads it:
public class Area extends Graphic {
private Shape _geometry;
// Adds geometry to format.
protected static final XmlFormat<Area> XML = new XmlFormat<Area>(Area.class) {
public void format(Area area, XmlElement xml) {
Graphic.XML.format(area, xml); // Call parent format.
xml.add(area._geometry,"Geometry");
}
public Area parse(XmlElement xml) {
Area area = (Area) Graphic.XML.parse(xml); // Call parent parse.
area._geometry = xml.get("Geometry");
return area;
}
};
}
ObjectWriter<Area> areaWriter = new ObjectWriter<Area>();
areaWriter.setPackagePrefix("g", "org.jscience.graphics.geom2d"); // Use namespace for package (optional).
areaWriter.write(area, new FileOutputStream("C:/area.xml"));
...
Area a = new ObjectReader<Area>().read(new FileInputStream("C:/area.xml"));
For multiple objects transmissions over open I/O streams,
javolution.xml.XmlInputStream and javolution.xml.XmlOutputStream are recommended.
<g:Area xmlns:j="http://javolution.org" xmlns:g="java:org.jscience.graphics.geom2d" isVisible="true">
<Paint j:class="java.awt.Color" rgb="#F3EBC6">
<Geometry j:class="org.jscience.graphics.geom2d.Polygon" id="1">
<Point x="123" y="-34">
<Point x="-43" y="-34">
<Point x="-12" y="123">
</Geometry>
</g:Area>
The following table illustrates the variety of xml representations supported (Foo class with a single String member named text):
| XML FORMAT | XML DATA |
|
<!-- Member as attribute --> <Foo text="This is a text"/> |
|
<!-- Member as anonymous nested element -->
<Foo>
<java.lang.String value="This is a text"/>
</Foo>
|
|
<!-- Member as Character Data -->
<Foo>
<![CDATA[This is a text]]>
</Foo>
|
|
<!-- Member as named element of unknown type -->
<Foo>
<text j:class="java.lang.String" value="This is a text"/>
</Foo>
|
|
<!-- Member as named element of known type -->
<Foo>
<text value="This is a text"/>
</Foo>
|
Applications may also temporarily change the classes aliases
and associated formats during parsing/formatting.
The XmlFormat does not have to use the class
public no-arg constructor (xml.object()), instances can be created using factory methods,
private constructors (with constructor parameters set from the XML element) or even retrieved from a collection (if the object is shared
or unique). For example:
public final class Point { // Immutable, no no-arg constructor.
protected static final XmlFormat<Point> XML = new XmlFormat<Point>(Point.class) {
public String identifier() {
return null; // Do not use references for points (always expanded).
}
public void format(Point point, XmlElement xml) {
xml.setAttribute("x", point._x);
xml.setAttribute("y", point._y);
}
public Point parse(XmlElement xml) {
return Point.valueOf(xml.getAttribute("x", 0.0), xml.getAttribute("y", 0.0));
}
};
private double _x;
private double _y;
private Point() {}; // No-arg constructor not visible.
public static Point valueOf(double x, double y) { ... }
}
...
private class MyPrivateGraphic extends Graphic { // Private class (can be inner class).
static final XmlFormat<MyPrivateGraphic> XML = new XmlFormat<MyPrivateGraphic>(MyPrivateGraphic.class) {
public MyPrivateGraphic allocate(XmlElement xml) {
return new MyPrivateGraphic();
}
public void format(MyPrivateGraphic g, XmlElement xml) {
Graphic.XML.format(g, xml); // Calls parent format.
}
public MyPrivateGraphic parse(XmlElement xml) {
return (MyPrivateGraphic) Graphic.XML.parse(xml); // Calls parent parse.
}
};
}
Document cross-references are supported, including circular references for xml format
implementing XmlFormat.allocate(xml).
Here is the XML representation of a list of three polygons
(the first one and the last one being shared) when references are enabled:
<java.util.ArrayList xmlns:j="http://javolution.org" xmlns:geom2d="java:org.jscience.graphics.geom2d" j:id="0">
<geom2d:Polygon j:id="1">
<Point x="123" y="-34"/>
<Point x="-43" y="-34"/>
<Point x="-12" y="123"/>
</geom2d:Polygon>
<geom2d:Polygon j:id="2">
<Point x="-43" y="-34"/>
<Point x="123" y="-34"/>
<Point x="-12" y="123"/>
</geom2d:Polygon>
<geom2d:Polygon j:ref="1"/>
</java.util.ArrayList>
Finally, here is a code excerpt illustrating how objects can be
efficiently transmitted over the network using the java.nio facility
instead of classic I/O (slower):
// Client thread.
ObjectReader or = new ObjectReader();
ByteBuffer bb = ByteBuffer.allocateDirect(XML_SIZE);
SocketChannel sc = SocketChannel.open(new InetSocketAddress(LOCAL_HOST, PORT));
sc.read(bb); // Reads socket into byte buffer.
bb.flip();
Object obj = or.read(bb); // Parses byte buffer.
bb.clear();
...
// Server thread.
ObjectWriter ow = new ObjectWriter();
ByteBuffer bb = ByteBuffer.allocateDirect(XML_SIZE);
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(new InetSocketAddress(PORT));
SocketChannel sc = ssc.accept(); // Waits for connections.
ow.write(obj, bb); // Formats object into byte buffer.
bb.flip();
sc.write(bb); // Sends byte buffer.
bb.clear();
When using NIO, the ByteBuffer capacity has to be large enough to hold
the largest XML representation of the objects being transmitted.
DMelt 3.0 © DataMelt by jWork.ORG