|
Javolution 6.0.0 java
|
Packages | |
| package | internal |
| package | sax |
| package | stream |
| package | ws |
Classes | |
| interface | DefaultXMLFormat |
| class | QName |
| class | XMLBinding |
| class | XMLContext |
| class | XMLFormat |
| class | XMLObjectReader |
| class | XMLObjectWriter |
| class | XMLReferenceResolver |
| interface | XMLSerializable |
Support for the encoding of objects, and the objects reachable from them, into XML; and the complementary reconstruction of the object graph from XML.
This page has been translated into Spanish language by Maria Ramos from Webhostinghub.com/support/edu.

Key Advantages:
The default XML format for a class is typically defined using the javolution.xml.DefaultXMLFormat annotation tag. [code] @DefaultXMLFormat(Graphic.XML.class)
public abstract class Graphic implements XMLSerializable { private boolean isVisible; private Paint paint; // null if none. private Stroke stroke; // null if none. private Transform transform; // null if none.
Default XML format with name associations (members identified by an unique name). See XMLFormat for examples of positional associations. public static class XML extends XMLFormat { public void write(Graphic g, OutputElement xml) throws XMLStreamException { xml.setAttribute("isVisible", g.isVisible); xml.add(g.paint, "Paint"); xml.add(g.stroke, "Stroke"); xml.add(g.transform, "Transform"); } public void read(InputElement xml, Graphic g) throws XMLStreamException { g.isVisible = xml.getAttribute("isVisible", true); g.paint = xml.get("Paint"); g.stroke = xml.get("Stroke"); g.transform = xml.get("Transform"); } }; }[/code] Sub-classes may override the inherited XML format: [code] @DefaultXMLFormat(Area.XML.class)
public class Area extends Graphic { private Shape geometry;
Adds geometry to format. public static class XML extends XMLFormat<Area> { XMLFormat graphicXML = new Graphic.XML(); public void write(Area area, OutputElement xml) throws XMLStreamException { graphicXML.write(area, xml); // Calls parent write. xml.add(area.geometry, "Geometry"); } public void read(InputElement xml, Area area) throws XMLStreamException { graphicXML.read(xml, area); // Calls parent read. area.geometry = xml.get("Geometry"); } }; }[/code]
The following writes a graphic area to a file, then reads it:
[code]
Creates some useful aliases for class names. XMLBinding binding = new XMLBinding(); binding.setAlias(Color.class, "Color"); binding.setAlias(Polygon.class, "Polygon"); binding.setClassAttribute("type"); // Use "type" instead of "class" for class attribute.
Writes the area to a file. XMLObjectWriter writer = XMLObjectWriter.newInstance(new FileOutputStream("C:/area.xml")); writer.setBinding(binding); // Optional. writer.setIndentation("\t"); // Optional (use tabulation for indentation). writer.write(area, "Area", Area.class); writer.close();
Reads the area back XMLObjectReader reader = XMLObjectReader.newInstance(new FileInputStream("C:/area.xml")); reader.setBinding(binding); Area a = reader.read("Area", Area.class); reader.close(); [/code]
Here is an example of valid XML representation for an area:
[code] <Area isVisible="true"> <Paint type="Color" rgb="#F3EBC6" > <Geometry type="Polygon"> <Vertex x="123" y="-34" > <Vertex x="-43" y="-34" > <Vertex x="-12" y="123" > </Geometry> </Area>[/code]
The following table illustrates the variety of XML representations supported (Foo class with a single String member named text):
<!-- 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>This is a text</Foo>
<!-- Member as named element of unknown type -->
<Foo>
<Text class="java.lang.String" value="This is a text"/>
</Foo>
[code]
XMLFormat<Foo> XML = new XMLFormat<Foo>(Foo.class) {
public void write(Foo foo, OutputElement xml) throws XMLStreamException {
xml.add(foo.text, "Text", String.class);
}
public void read(InputElement xml, Foo foo) throws XMLStreamException {
foo.text = xml.get("Text", String.class);
}
};[/code]
<!-- Member as named element of actual type known -->
<Foo>
<Text value="This is a text"/>
</Foo>
</tbody>
XML format do not have to use the classes
public no-arg constructors, 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:
[code]
@DefaultXMLFormat(Point.XML.class)
public final class Point implements XMLSerializable {
private int x;
private int y;
private Point() {}; // No-arg constructor not visible.
public static Point valueOf(int x, int y) { ... }
public static class XML = new XMLFormat<Point>() {
public boolean isReferencable() {
return false; // Always manipulated by value.
}
public Point newInstance(Class<Point> cls, InputElement xml) throws XMLStreamException {
return Point.valueOf(xml.getAttribute("x", 0), xml.getAttribute("y", 0));
}
public void write(Point point, OutputElement xml) throws XMLStreamException {
xml.setAttribute("x", point.x);
xml.setAttribute("y", point.y);
}
public void read(InputElement xml, Point point) throws XMLStreamException {
Do nothing immutable.
}
};
}[/code]
Document cross-references are supported, including circular references.
Let's take for example:
[code]
@DefaultXMLFormat(xml=Polygon.XML.class)
public class Polygon implements Shape, XMLSerializable {
private Point[] vertices;
public static class XML extends XMLFormat<Polygon> {
public void write(Polygon polygon, OutputElement xml) throws XMLStreamException {
xml.setAttibutes("count", vertices.length);
for (Point p : vertices) {
xml.add(p, "Vertex", Point.class);
}
}
public void read(InputElement xml, Polygon polygon) throws XMLStreamException {
int count = xml.getAttributes("count", 0);
polygon.vertices = new Point[count];
for (int i=0; i < count; i++) {
vertices[i] = xml.get("Vertex", Point.class);
}
}
};
}
Polygon[] polygons = new Polygon[] {p1, p2, p1};
...
TextBuilder xml = TextBuilder.newInstance();
AppendableWriter out = new AppendableWriter().setOutput(xml)
XMLObjectWriter writer = XMLObjectWriter.newInstance(out);
writer.setXMLReferenceResolver(new XMLReferenceResolver()); // Enables cross-references.
writer.write(polygons, "Polygons", Polygon[].class);
writer.close();
System.out.println(xml);
[/code]
Prints the following (noticed that the first polygon and last one are being shared).
[code]
<Polygons length="3">
<Polygon id="0" count="3">
<Vertex x="123" y="-34" >
<Vertex x="-43" y="-34" >
<Vertex x="-12" y="123" >
</Polygon>
<Polygon id="1" count="3">
<Vertex x="-43" y="-34" >
<Vertex x="123" y="-34" >
<Vertex x="-12" y="123" >
</Polygon>
<Polygon ref="0">
</Polygons>[/code]
ALGORITHMS:
Our XMLObjectReader/XMLObjectWriter are in fact simple wrappers around our Javolution high-performance StAX-like XMLStreamReader and XMLStreamWriter classes. The logic of these wrappers is described below:
OutputElement.add(object, name, uri, class):
1. if (object == null) return
2. getStreamWriter().writeStartElement(uri, name)
3. isReference = referenceResolver.writeReference(object, this)
4. if (!isReference) binding.getFormat(class).write(object, this)
5. getStreamWriter().writeEndElement()
6. end
InputElement.get(name, uri, class):
1. if (!getStreamReader().getLocalName().equals(name) || !getStreamReader().getNamespaceURI().equals(uri)) return null
2. object = referenceResolver.readReference(inputElement)
3. if (object != null) Goto 8 // Found reference
4. format = binding.getFormat(class)
5. object = format.newInstance(class, inputElement)
6. referenceResolver.createReference(object, inputElement) // Done before parsing to support circular references.
7. format.read(inputElement, object)
8. getStreamReader().nextTag()
9. end</p