You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@marmotta.apache.org by ss...@apache.org on 2013/09/06 14:26:57 UTC
[05/18] temporarily added a patched version of javolution with fast
collections, because the released version has several bugs (see
https://java.net/jira/browse/JAVOLUTION-106 and
https://java.net/jira/browse/JAVOLUTION-105)
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/XMLFormat.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/XMLFormat.java b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLFormat.java
new file mode 100644
index 0000000..ba201d8
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLFormat.java
@@ -0,0 +1,1029 @@
+/*
+ * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+ * Copyright (C) 2012 - Javolution (http://javolution.org/)
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software is
+ * freely granted, provided that this notice is preserved.
+ */
+package javolution.xml;
+
+import javolution.text.CharArray;
+import javolution.text.TextBuilder;
+import javolution.text.TextContext;
+import javolution.text.TextFormat;
+import javolution.xml.internal.stream.XMLStreamReaderImpl;
+import javolution.xml.internal.stream.XMLStreamWriterImpl;
+import javolution.xml.sax.Attributes;
+import javolution.xml.stream.XMLStreamException;
+import javolution.xml.stream.XMLStreamReader;
+import javolution.xml.stream.XMLStreamWriter;
+
+/**
+ * <p> This class represents the format base class for XML serialization and
+ * deserialization.</p>
+ *
+ * <p> Instances of this class are typically retrieved from the
+ * {@link XMLContext} (OSGi service or not).
+ * [code]
+ * @Format(xml=GraphicXML.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.
+ *
+ * // XML format with positional associations (members identified by their position),
+ * // see XML package description for examples of name associations.
+ * public static class GraphicXML extends XMLFormat<Graphic> {
+ * public void write(Graphic g, OutputElement xml) {
+ * xml.setAttribute("isVisible", g.isVisible);
+ * xml.add(g.paint); // First.
+ * xml.add(g.stroke); // Second.
+ * xml.add(g.transform); // Third.
+ * }
+ * public void read(InputElement xml, Graphic g) {
+ * g.isVisible = xml.getAttribute("isVisible", true);
+ * g.paint = xml.getNext();
+ * g.stroke = xml.getNext();
+ * g.transform = xml.getNext();
+ * return g;
+ * }
+ * };
+ * }
+ * [/code]
+ *
+ * <p> Due to the sequential nature of XML serialization/deserialization,
+ * formatting/parsing of XML attributes should always be performed before
+ * formatting/parsing of the XML content.</p>
+ *
+ * <p> The mapping between classes and XML formats can be overriden
+ * through {@link XMLBinding} instances.
+ * Here is an example of serialization/deserialization:
+ * [code]
+ * // Creates a list holding diverse objects.
+ * List list = new ArrayList();
+ * list.add("John Doe");
+ * list.add(null);
+ * Map map = new FastMap();
+ * map.put("ONE", 1);
+ * map.put("TWO", 2);
+ * list.add(map);
+ *
+ * // Use of custom binding.
+ * XMLBinding binding = new XMLBinding();
+ * binding.setAlias(FastMap.class, "Map");
+ * binding.setAlias(String.class, "String");
+ * binding.setAlias(Integer.class, "Integer");
+ *
+ * // Formats the list to XML .
+ * OutputStream out = new FileOutputStream("C:/list.xml");
+ * XMLObjectWriter writer = new XMLObjectWriter().setOutput(out).setBinding(binding);
+ * writer.write(list, "MyList", ArrayList.class);
+ * writer.close();
+ * [/code]
+ *
+ * Here is the output <code>list.xml</code> document produced:[code]
+ *
+ * <MyList>
+ * <String value="John Doe"/>
+ * <Null/>
+ * <Map>
+ * <Key class="String" value="ONE"/>
+ * <Value class="Integer" value="1"/>
+ * <Key class="String" value="TWO"/>
+ * <Value class="Integer" value="2"/>
+ * </Map>
+ * </MyList>
+ * [/code]
+ *
+ * The list can be read back with the following code:
+ * [code]
+ * // Reads back to a FastTable instance.
+ * InputStream in = new FileInputStream("C:/list.xml");
+ * XMLObjectReader reader = new XMLObjectReader().setInput(in).setBinding(binding);
+ * FastTable table = reader.read("MyList", FastTable.class);
+ * reader.close();
+ * [/code]
+ * </p>
+ *
+ * <p> <i>Note:</i> Any type for which a {@link TextFormat text format} is
+ * defined can be represented as a XML attribute.</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 5.4, December 1, 2009
+ */
+public abstract class XMLFormat<T> {
+
+ /**
+ * Holds <code>null</code> representation.
+ */
+ private static final String NULL = "Null";
+
+ /**
+ * Default constructor.
+ */
+ protected XMLFormat() {}
+
+ /**
+ * Indicates if the object serialized through this format can be referenced
+ * to (default <code>true</code>). This method can be overriden to return
+ * <code>false</code> if serialized objects are manipulated "by value".
+ *
+ * @return <code>true</code> if serialized object may hold a reference;
+ * <code>false</code> otherwise.
+ * @see XMLReferenceResolver
+ */
+ public boolean isReferenceable() {
+ return true;
+ }
+
+ /**
+ * Allocates a new object of the specified class from the specified
+ * XML input element. By default, this method returns an object created
+ * using the public no-arg constructor of the specified class.
+ * XML formats may override this method in order to use private/multi-arg
+ * constructors.
+ *
+ * @param cls the class of the object to return.
+ * @param xml the XML input element.
+ * @return the object corresponding to the specified XML element.
+ */
+ public T newInstance(Class<? extends T> cls, InputElement xml)
+ throws XMLStreamException {
+ try {
+ return cls.newInstance();
+ } catch (InstantiationException e) {
+ throw new XMLStreamException(e);
+ } catch (IllegalAccessException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+
+ /**
+ * Formats an object into the specified XML output element.
+ *
+ * @param obj the object to format.
+ * @param xml the <code>XMLElement</code> destination.
+ */
+ public abstract void write(T obj, OutputElement xml)
+ throws XMLStreamException;
+
+ /**
+ * Parses an XML input element into the specified object.
+ *
+ * @param xml the XML element to parse.
+ * @param obj the object created through {@link #newInstance}
+ * and to setup from the specified XML element.
+ */
+ public abstract void read(InputElement xml, T obj)
+ throws XMLStreamException;
+
+ /**
+ * This class represents an input XML element (unmarshalling).
+ */
+ @SuppressWarnings("unchecked")
+ public static final class InputElement {
+
+ /**
+ * Holds the stream reader.
+ */
+ final XMLStreamReaderImpl _reader = new XMLStreamReaderImpl();
+
+ /**
+ * Holds the XML binding.
+ */
+ private XMLBinding _binding;
+
+ /**
+ * Holds the reference resolver.
+ */
+ private XMLReferenceResolver _referenceResolver;
+
+ /**
+ * Indicates if the reader is currently positioned on the next element.
+ */
+ private boolean _isReaderAtNext;
+
+ /**
+ * Default constructor.
+ */
+ InputElement() {
+ reset();
+ }
+
+ /**
+ * Returns the StAX-like stream reader (provides complete control
+ * over the unmarshalling process).
+ *
+ * @return the stream reader.
+ */
+ public XMLStreamReader getStreamReader() {
+ return _reader;
+ }
+
+ /**
+ * Indicates if more nested XML element can be read. This method
+ * positions the {@link #getStreamReader reader} at the start of the
+ * next XML element to be read (if any).
+ *
+ * @return <code>true</code> if there is more XML element to be read;
+ * <code>false</code> otherwise.
+ */
+ public boolean hasNext() throws XMLStreamException {
+ if (!_isReaderAtNext) {
+ _isReaderAtNext = true;
+ _reader.nextTag();
+ }
+ return _reader.getEventType() == XMLStreamReader.START_ELEMENT;
+ }
+
+ /**
+ * Returns the next object whose type is identified by the local name
+ * and URI of the current XML element.
+ *
+ * @return the next nested object which can be <code>null</code>.
+ * @throws XMLStreamException if <code>hasNext() == false</code>.
+ */
+ public <T> T getNext() throws XMLStreamException {
+ if (!hasNext()) // Asserts isReaderAtNext == true
+ throw new XMLStreamException("No more element to read",
+ _reader.getLocation());
+
+ // Checks for null.
+ if (_reader.getLocalName().equals(NULL)) {
+ if (_reader.next() != XMLStreamReader.END_ELEMENT)
+ throw new XMLStreamException("Non Empty Null Element");
+ _isReaderAtNext = false;
+ return null;
+ }
+
+ Object ref = readReference();
+ if (ref != null)
+ return (T) ref;
+
+ // Retrieves object's class from element tag.
+ Class<?> cls = _binding.readClass(_reader, false);
+ return readInstanceOf(cls);
+ }
+
+ /**
+ * Returns the object whose type is identified by a XML class attribute
+ * only if the XML element has the specified local name.
+ *
+ * @param name the local name of the next element.
+ * @return the next nested object or <code>null</code>.
+ */
+ public <T> T get(String name) throws XMLStreamException {
+ if (!hasNext()// Asserts isReaderAtNext == true
+ || !_reader.getLocalName().equals(name))
+ return null;
+
+ Object ref = readReference();
+ if (ref != null)
+ return (T) ref;
+
+ // Retrieves object's class from class attribute.
+ Class<?> cls = _binding.readClass(_reader, true);
+ return readInstanceOf(cls);
+ }
+
+ /**
+ * Returns the object whose type is identified by a XML class attribute
+ * only if the XML element has the specified local name and URI.
+ *
+ * @param localName the local name.
+ * @param uri the namespace URI or <code>null</code>.
+ * @return the next nested object or <code>null</code>.
+ */
+ public <T> T get(String localName, String uri)
+ throws XMLStreamException {
+ if (uri == null)
+ return (T) get(localName);
+
+ if (!hasNext()// Asserts isReaderAtNext == true
+ || !_reader.getLocalName().equals(localName)
+ || !_reader.getNamespaceURI().equals(uri))
+ return null;
+
+ Object ref = readReference();
+ if (ref != null)
+ return (T) ref;
+
+ // Retrieves object's class from class attribute.
+ Class<?> cls = _binding.readClass(_reader, true);
+ return readInstanceOf(cls);
+ }
+
+ /**
+ * Returns the object of specified type only if the XML element has the
+ * specified local name.
+ *
+ * @param name the local name of the element to match.
+ * @param cls the class identifying the format of the object to return.
+ * @return the next nested object or <code>null</code>.
+ */
+ public <T> T get(String name, Class<T> cls) throws XMLStreamException {
+ if (!hasNext()// Asserts isReaderAtNext == true
+ || !_reader.getLocalName().equals(name))
+ return null;
+
+ Object ref = readReference();
+ if (ref != null)
+ return (T) ref;
+
+ return readInstanceOf(cls);
+ }
+
+ /**
+ * Returns the object of specified type only if the
+ * XML element has the specified local name and namespace URI.
+ *
+ * @param localName the local name.
+ * @param uri the namespace URI or <code>null</code>.
+ * @param cls the class identifying the format of the object to return.
+ * @return the next nested object or <code>null</code>.
+ */
+ public <T> T get(String localName, String uri, Class<T> cls)
+ throws XMLStreamException {
+ if (uri == null)
+ return get(localName, cls);
+
+ if (!hasNext()// Asserts isReaderAtNext == true
+ || !_reader.getLocalName().equals(localName)
+ || !_reader.getNamespaceURI().equals(uri))
+ return null;
+
+ Object ref = readReference();
+ if (ref != null)
+ return (T) ref;
+
+ return readInstanceOf(cls);
+ }
+
+ // Returns the referenced object if any.
+ private Object readReference() throws XMLStreamException {
+ if (_referenceResolver == null)
+ return null;
+ Object ref = _referenceResolver.readReference(this);
+ if (ref == null)
+ return null;
+ if (_reader.next() != XMLStreamReader.END_ELEMENT)
+ throw new XMLStreamException("Non Empty Reference Element");
+ _isReaderAtNext = false;
+ return ref;
+ }
+
+ // Builds object of specified class.
+ @SuppressWarnings("rawtypes")
+ private <T> T readInstanceOf(Class cls) throws XMLStreamException {
+
+ // Retrieves format.
+ XMLFormat xmlFormat = _binding.getFormat(cls);
+
+ // Creates object.
+ _isReaderAtNext = false; // Makes attributes accessible.
+ Object obj = xmlFormat.newInstance(cls, this);
+
+ // Adds reference (before reading to support circular reference).
+ if (_referenceResolver != null) {
+ _referenceResolver.createReference(obj, this);
+ }
+
+ // Parses xml.
+ xmlFormat.read(this, obj);
+ if (hasNext()) // Asserts _isReaderAtNext == true
+ throw new XMLStreamException("Incomplete element reading",
+ _reader.getLocation());
+ _isReaderAtNext = false; // Skips end element.
+ return (T) obj;
+ }
+
+ /**
+ * Returns the content of a text-only element (equivalent to
+ * {@link javolution.xml.stream.XMLStreamReader#getElementText
+ * getStreamReader().getElementText()}).
+ *
+ * @return the element text content or an empty sequence if none.
+ */
+ public CharArray getText() throws XMLStreamException {
+ CharArray txt = _reader.getElementText();
+ _isReaderAtNext = true; // End element is next.
+ return txt;
+ }
+
+ /**
+ * Returns the attributes for this XML input element.
+ *
+ * @return the attributes mapping.
+ */
+ public Attributes getAttributes() throws XMLStreamException {
+ if (_isReaderAtNext)
+ throw new XMLStreamException(
+ "Attributes should be read before content");
+ return _reader.getAttributes();
+ }
+
+ /**
+ * Searches for the attribute having the specified name.
+ *
+ * @param name the name of the attribute.
+ * @return the value for the specified attribute or <code>null</code>
+ * if the attribute is not found.
+ */
+ public CharArray getAttribute(String name) throws XMLStreamException {
+ if (_isReaderAtNext)
+ throw new XMLStreamException(
+ "Attributes should be read before reading content");
+ return _reader.getAttributeValue(null, name);
+ }
+
+ /**
+ * Returns the specified <code>String</code> attribute.
+ *
+ * @param name the name of the attribute.
+ * @param defaultValue a default value.
+ * @return the value for the specified attribute or
+ * the <code>defaultValue</code> if the attribute is not found.
+ */
+ public String getAttribute(String name, String defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ return (value != null) ? value.toString() : defaultValue;
+ }
+
+ /**
+ * Returns the specified <code>boolean</code> attribute.
+ *
+ * @param name the name of the attribute searched for.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the <code>boolean</code> value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public boolean getAttribute(String name, boolean defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ return (value != null) ? value.toBoolean() : defaultValue;
+ }
+
+ /**
+ * Returns the specified <code>char</code> attribute.
+ *
+ * @param name the name of the attribute searched for.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the <code>char</code> value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public char getAttribute(String name, char defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ if (value == null)
+ return defaultValue;
+ if (value.length() != 1)
+ throw new XMLStreamException(
+ "Single character expected (read '" + value + "')");
+ return value.charAt(0);
+ }
+
+ /**
+ * Returns the specified <code>byte</code> attribute. This method handles
+ * string formats that are used to represent octal and hexadecimal numbers.
+ *
+ * @param name the name of the attribute searched for.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the <code>byte</code> value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public byte getAttribute(String name, byte defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ return (value != null) ? (byte) value.toInt() : defaultValue;
+ }
+
+ /**
+ * Returns the specified <code>short</code> attribute. This method handles
+ * string formats that are used to represent octal and hexadecimal numbers.
+ *
+ * @param name the name of the attribute searched for.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the <code>short</code> value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public short getAttribute(String name, short defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ return (value != null) ? (short) value.toInt() : defaultValue;
+ }
+
+ /**
+ * Returns the specified <code>int</code> attribute. This method handles
+ * string formats that are used to represent octal and hexadecimal numbers.
+ *
+ * @param name the name of the attribute searched for.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the <code>int</code> value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public int getAttribute(String name, int defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ return (value != null) ? value.toInt() : defaultValue;
+ }
+
+ /**
+ * Returns the specified <code>long</code> attribute. This method handles
+ * string formats that are used to represent octal and hexadecimal numbers.
+ *
+ * @param name the name of the attribute searched for.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the <code>long</code> value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public long getAttribute(String name, long defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ return (value != null) ? value.toLong() : defaultValue;
+ }
+
+ /**
+ * Returns the specified <code>float</code> attribute.
+ *
+ * @param name the name of the attribute searched for.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the <code>float</code> value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public float getAttribute(String name, float defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ return (value != null) ? value.toFloat() : defaultValue;
+ }
+
+ /**
+ * Returns the specified <code>double</code> attribute.
+ *
+ * @param name the name of the attribute searched for.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the <code>double</code> value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public double getAttribute(String name, double defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ return (value != null) ? value.toDouble() : defaultValue;
+ }
+
+ /**
+ * Returns the attribute of same type as the specified
+ * default value.
+ *
+ * @param name the name of the attribute.
+ * @param defaultValue the value returned if the attribute is not found.
+ * @return the parse value for the specified attribute or
+ * the default value if the attribute is not found.
+ */
+ public <T> T getAttribute(String name, T defaultValue)
+ throws XMLStreamException {
+ CharArray value = getAttribute(name);
+ if (value == null)
+ return defaultValue;
+ // Parses attribute value.
+ Class<?> type = defaultValue.getClass();
+ TextFormat<?> format = TextContext.getFormat(type);
+ if (format == null)
+ throw new XMLStreamException("No TextFormat defined for "
+ + type);
+ return (T) format.parse(value);
+ }
+
+ // Sets XML binding.
+ void setBinding(XMLBinding xmlBinding) {
+ _binding = xmlBinding;
+ }
+
+ // Sets XML reference resolver.
+ void setReferenceResolver(XMLReferenceResolver xmlReferenceResolver) {
+ _referenceResolver = xmlReferenceResolver;
+ }
+
+ // Resets for reuse.
+ void reset() {
+ _binding = XMLBinding.DEFAULT;
+ _isReaderAtNext = false;
+ _reader.reset();
+ _referenceResolver = null;
+ }
+ }
+
+ /**
+ * This class represents an output XML element (marshalling).
+ */
+ @SuppressWarnings("unchecked")
+ public static final class OutputElement {
+
+ /**
+ * Holds the stream writer.
+ */
+ final XMLStreamWriterImpl _writer = new XMLStreamWriterImpl();
+
+ /**
+ * Holds the XML binding.
+ */
+ private XMLBinding _binding;
+
+ /**
+ * Holds the reference resolver.
+ */
+ private XMLReferenceResolver _referenceResolver;
+
+ /**
+ * Default constructor.
+ */
+ OutputElement() {
+ reset();
+ }
+
+ /**
+ * Returns the StAX-like stream writer (provides complete control over
+ * the marshalling process).
+ *
+ * @return the stream writer.
+ */
+ public XMLStreamWriter getStreamWriter() {
+ return _writer;
+ }
+
+ /**
+ * Adds the specified object or <code>null</code> as an anonymous
+ * nested element of unknown type.
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ */
+ public void add(Object obj) throws XMLStreamException {
+ if (obj == null) {
+ _writer.writeEmptyElement(NULL);
+ return;
+ }
+
+ // Writes start element.
+ Class<?> cls = obj.getClass();
+ _binding.writeClass(cls, _writer, false);
+
+ // Checks if reference written.
+ XMLFormat<Object> xmlFormat = (XMLFormat<Object>) _binding
+ .getFormat(cls);
+ if (xmlFormat.isReferenceable() && writeReference(obj))
+ return;
+
+ xmlFormat.write(obj, this);
+ _writer.writeEndElement();
+ }
+
+ /**
+ * Adds the specified object as a named nested element of unknown type
+ * (<code>null</code> objects are ignored).
+ * The nested XML element contains a class attribute identifying
+ * the object type.
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ * @param name the name of the nested element.
+ */
+ public void add(Object obj, String name) throws XMLStreamException {
+ if (obj == null)
+ return;
+
+ // Writes start element.
+ _writer.writeStartElement(name);
+
+ // Writes class attribute.
+ Class<?> cls = obj.getClass();
+ _binding.writeClass(cls, _writer, true);
+
+ // Checks if reference written.
+ XMLFormat<Object> xmlFormat = (XMLFormat<Object>) _binding
+ .getFormat(cls);
+ if (xmlFormat.isReferenceable() && writeReference(obj))
+ return;
+
+ xmlFormat.write(obj, this);
+ _writer.writeEndElement();
+ }
+
+ /**
+ * Adds the specified object as a fully qualified nested element of
+ * unknown type (<code>null</code> objects are ignored).
+ * The nested XML element contains a class attribute identifying
+ * the object type.
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ * @param localName the local name of the nested element.
+ * @param uri the namespace URI of the nested element.
+ */
+ public void add(Object obj, String localName, String uri)
+ throws XMLStreamException {
+ if (obj == null)
+ return;
+
+ // Writes start element.
+ _writer.writeStartElement(uri, localName);
+
+ // Writes class attribute.
+ Class<?> cls = obj.getClass();
+ _binding.writeClass(cls, _writer, true);
+
+ // Checks if reference written.
+ XMLFormat<Object> xmlFormat = (XMLFormat<Object>) _binding
+ .getFormat(cls);
+ if (xmlFormat.isReferenceable() && writeReference(obj))
+ return;
+
+ xmlFormat.write(obj, this);
+ _writer.writeEndElement();
+ }
+
+ /**
+ * Adds the specified object as a named nested element of specified
+ * actual type (<code>null</code> objects are ignored).
+ * The nested XML element does not contain any class attribute.
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ * @param name the name of the nested element.
+ * @param cls the class identifying the format of the specified object.
+ */
+ public <T> void add(T obj, String name, Class<T> cls)
+ throws XMLStreamException {
+ if (obj == null)
+ return;
+
+ // Writes start element.
+ _writer.writeStartElement(name);
+
+ // Checks if reference written.
+ XMLFormat<T> xmlFormat = (XMLFormat<T>) _binding.getFormat(cls);
+ if (xmlFormat.isReferenceable() && writeReference(obj))
+ return;
+
+ xmlFormat.write(obj, this);
+ _writer.writeEndElement();
+ }
+
+ /**
+ * Adds the specified object as a fully qualified nested element of
+ * specified actual type (<code>null</code> objects are ignored).
+ * The nested XML element does not contain any class attribute.
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ * @param localName the local name of the nested element.
+ * @param uri the namespace URI of the nested element.
+ * @param cls the class identifying the format of the specified object.
+ */
+ public <T> void add(T obj, String localName, String uri, Class<T> cls)
+ throws XMLStreamException {
+ if (obj == null)
+ return;
+
+ // Writes start element.
+ _writer.writeStartElement(uri, localName);
+
+ // Checks if reference written.
+ XMLFormat<T> xmlFormat = (XMLFormat<T>) _binding.getFormat(cls);
+ if (xmlFormat.isReferenceable() && writeReference(obj))
+ return;
+
+ xmlFormat.write(obj, this);
+ _writer.writeEndElement();
+ }
+
+ // Returns true if reference written.
+ private boolean writeReference(Object obj) throws XMLStreamException {
+ if ((_referenceResolver == null)
+ || !_referenceResolver.writeReference(obj, this))
+ return false;
+ _writer.writeEndElement();
+ return true; // Reference written.
+ }
+
+ /**
+ * Adds the content of a text-only element (equivalent to {@link
+ * javolution.xml.stream.XMLStreamWriter#writeCharacters(CharSequence)
+ * getStreamWriter().writeCharacters(text)}).
+ *
+ * @param text the element text content or an empty sequence if none.
+ */
+ public void addText(CharSequence text) throws XMLStreamException {
+ _writer.writeCharacters(text);
+ }
+
+ /**
+ * Equivalent to {@link #addText(CharSequence)}
+ * (for J2ME compatibility).
+ *
+ * @param text the element text content or an empty sequence if none.
+ */
+ public void addText(String text) throws XMLStreamException {
+ _writer.writeCharacters(text);
+ }
+
+ /**
+ * Sets the specified <code>CharSequence</code> attribute
+ * (<code>null</code> values are ignored).
+ *
+ * @param name the attribute name.
+ * @param value the attribute value or <code>null</code>.
+ */
+ public void setAttribute(String name, CharSequence value)
+ throws XMLStreamException {
+ if (value == null)
+ return;
+ _writer.writeAttribute(name, value);
+ }
+
+ /**
+ * Sets the specified <code>String</code> attribute
+ * (<code>null</code> values are ignored).
+ *
+ * @param name the attribute name.
+ * @param value the attribute value.
+ */
+ public void setAttribute(String name, String value)
+ throws XMLStreamException {
+ if (value == null)
+ return;
+ _writer.writeAttribute(name, value);
+ }
+
+ /**
+ * Sets the specified <code>boolean</code> attribute.
+ *
+ * @param name the attribute name.
+ * @param value the <code>boolean</code> value for the specified attribute.
+ */
+ public void setAttribute(String name, boolean value)
+ throws XMLStreamException {
+ setAttribute(name, _tmpTextBuilder.clear().append(value));
+ }
+
+ private TextBuilder _tmpTextBuilder = new TextBuilder();
+
+ /**
+ * Sets the specified <code>char</code> attribute.
+ *
+ * @param name the attribute name.
+ * @param value the <code>char</code> value for the specified attribute.
+ */
+ public void setAttribute(String name, char value)
+ throws XMLStreamException {
+ setAttribute(name,
+ (TextBuilder) _tmpTextBuilder.clear().append(value));
+ }
+
+ /**
+ * Sets the specified <code>byte</code> attribute.
+ *
+ * @param name the attribute name.
+ * @param value the <code>byte</code> value for the specified attribute.
+ */
+ public void setAttribute(String name, byte value)
+ throws XMLStreamException {
+ setAttribute(name, _tmpTextBuilder.clear().append(value));
+ }
+
+ /**
+ * Sets the specified <code>short</code> attribute.
+ *
+ * @param name the attribute name.
+ * @param value the <code>short</code> value for the specified attribute.
+ */
+ public void setAttribute(String name, short value)
+ throws XMLStreamException {
+ setAttribute(name, _tmpTextBuilder.clear().append(value));
+ }
+
+ /**
+ * Sets the specified <code>int</code> attribute.
+ *
+ * @param name the attribute name.
+ * @param value the <code>int</code> value for the specified attribute.
+ */
+ public void setAttribute(String name, int value)
+ throws XMLStreamException {
+ setAttribute(name, _tmpTextBuilder.clear().append(value));
+ }
+
+ /**
+ * Sets the specified <code>long</code> attribute.
+ *
+ * @param name the attribute name.
+ * @param value the <code>long</code> value for the specified attribute.
+ */
+ public void setAttribute(String name, long value)
+ throws XMLStreamException {
+ setAttribute(name, _tmpTextBuilder.clear().append(value));
+ }
+
+ /**
+ * Sets the specified <code>float</code> attribute.
+ *
+ * @param name the attribute name.
+ * @param value the <code>float</code> value for the specified attribute.
+ */
+ public void setAttribute(String name, float value)
+ throws XMLStreamException {
+ setAttribute(name, _tmpTextBuilder.clear().append(value));
+ }
+
+ /**
+ * Sets the specified <code>double</code> attribute.
+ *
+ * @param name the attribute name.
+ * @param value the <code>double</code> value for the specified attribute.
+ */
+ public void setAttribute(String name, double value)
+ throws XMLStreamException {
+ setAttribute(name, _tmpTextBuilder.clear().append(value));
+ }
+
+ /**
+ * Sets the specified attribute using its associated
+ * {@link javolution.text.TextFormat TextFormat}.
+ *
+ * @param name the name of the attribute.
+ * @param value the value for the specified attribute
+ * or <code>null</code> in which case the attribute is not set.
+ */
+ public void setAttribute(String name, Object value)
+ throws XMLStreamException {
+ if (value == null)
+ return;
+ setAttribute(name, _tmpTextBuilder.clear().append(value.toString()));
+ }
+
+ // Sets XML binding.
+ void setBinding(XMLBinding xmlBinding) {
+ _binding = xmlBinding;
+ }
+
+ // Sets XML reference resolver.
+ void setReferenceResolver(XMLReferenceResolver xmlReferenceResolver) {
+ _referenceResolver = xmlReferenceResolver;
+ }
+
+ // Resets for reuse.
+ void reset() {
+ _binding = XMLBinding.DEFAULT;
+ _writer.reset();
+ _writer.setRepairingNamespaces(true);
+ _writer.setAutomaticEmptyElements(true);
+ _referenceResolver = null;
+ }
+ }
+
+ /**
+ * Returns the default XML format for any object having a
+ * {@link TextFormat plain text format}; this XML representation consists
+ * of the plain text representation of the object as a "value" attribute.
+ */
+ public static class Default extends XMLFormat<Object> {
+
+ /**
+ * Default constructor.
+ */
+ public Default() {}
+
+ @Override
+ public boolean isReferenceable() {
+ return false; // Always by value (immutable).
+ }
+
+ @Override
+ public Object newInstance(Class<?> cls,
+ javolution.xml.XMLFormat.InputElement xml)
+ throws XMLStreamException {
+ TextFormat<?> format = TextContext.getFormat(cls);
+ if (format == null)
+ throw new XMLStreamException(
+ "No TextFormat defined to parse instances of " + cls);
+ CharArray value = xml.getAttribute("value");
+ if (value == null)
+ throw new XMLStreamException(
+ "Missing value attribute (to be able to parse the instance of "
+ + cls + ")");
+ return format.parse(value);
+ }
+
+ public void read(XMLFormat.InputElement xml, Object obj)
+ throws XMLStreamException {
+ // Do nothing.
+ }
+
+ @SuppressWarnings("unchecked")
+ public void write(Object obj, XMLFormat.OutputElement xml)
+ throws XMLStreamException {
+ TextBuilder tmp = new TextBuilder();
+ TextFormat<?> tf = TextContext.getFormat(obj.getClass());
+ ((TextFormat<Object>) tf).format(obj, tmp);
+ xml.setAttribute("value", tmp);
+ }
+
+ };
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/XMLObjectReader.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/XMLObjectReader.java b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLObjectReader.java
new file mode 100644
index 0000000..f51ebaf
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLObjectReader.java
@@ -0,0 +1,291 @@
+/*
+ * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+ * Copyright (C) 2012 - Javolution (http://javolution.org/)
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software is
+ * freely granted, provided that this notice is preserved.
+ */
+package javolution.xml;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import javolution.xml.internal.stream.XMLStreamReaderImpl;
+import javolution.xml.stream.XMLStreamException;
+import javolution.xml.stream.XMLStreamReader;
+
+/**
+ * <p> This class restores objects which have been serialized in XML
+ * format using an {@link XMLObjectWriter}.</p>
+ *
+ * <p> When the XML document is parsed, each elements are recursively
+ * processed and Java objects are created using the {@link XMLFormat}
+ * of the class as identified by the {@link XMLBinding}.</p>
+ *
+ * <p> Multiple objects can be read from the same XML input.
+ * For example:[code]
+ * XMLObjectReader reader = XMLObjectReader.newInstance(inputStream);
+ * while (reader.hasNext()) {
+ * Message message = reader.read("Message", Message.class);
+ * }
+ * reader.close(); // The underlying stream is closed.
+ * [/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, September 4, 2006
+ */
+public class XMLObjectReader {
+
+ /**
+ * Hold the xml element used when parsing.
+ */
+ private final XMLFormat.InputElement _xml = new XMLFormat.InputElement();
+
+ /**
+ * Holds reader if any.
+ */
+ private Reader _reader;
+
+ /**
+ * Holds input stream if any.
+ */
+ private InputStream _inputStream;
+
+ /**
+ * Returns a XML object reader having the specified
+ * input stream as input.
+ *
+ * @param in the input stream.
+ */
+ public static XMLObjectReader newInstance(InputStream in)
+ throws XMLStreamException {
+ XMLObjectReader reader = new XMLObjectReader();
+ reader.setInput(in);
+ return reader;
+ }
+
+ /**
+ * Returns a XML object reader (potentially recycled) having the specified
+ * input stream/encoding as input.
+ *
+ * @param in the input stream.
+ * @param encoding the input stream encoding
+ */
+ public static XMLObjectReader newInstance(InputStream in, String encoding)
+ throws XMLStreamException {
+ XMLObjectReader reader = new XMLObjectReader();
+ reader.setInput(in, encoding);
+ return reader;
+ }
+
+ /**
+ * Returns a XML object reader (potentially recycled) having the specified
+ * reader as input.
+ *
+ * @param in the reader source.
+ */
+ public static XMLObjectReader newInstance(Reader in)
+ throws XMLStreamException {
+ XMLObjectReader reader = new XMLObjectReader();
+ reader.setInput(in);
+ return reader;
+ }
+
+ /**
+ * Default constructor.
+ */
+ public XMLObjectReader() {}
+
+ /**
+ * Returns the stream reader being used by this reader (it can be
+ * used to set prefix, read prologs, etc).
+ *
+ * @return the stream reader.
+ */
+ public XMLStreamReader getStreamReader() {
+ return _xml._reader;
+ }
+
+ /**
+ * Sets the input stream source for this XML object reader
+ * (encoding retrieved from XML prolog if any).
+ *
+ * @param in the source input stream.
+ * @return <code>this</code>
+ * @see XMLStreamReaderImpl#setInput(InputStream)
+ */
+ public XMLObjectReader setInput(InputStream in) throws XMLStreamException {
+ if ((_inputStream != null) || (_reader != null))
+ throw new IllegalStateException("Reader not closed or reset");
+ _xml._reader.setInput(in);
+ _inputStream = in;
+ return this;
+ }
+
+ /**
+ * Sets the input stream source and encoding for this XML object reader.
+ *
+ * @param in the input source.
+ * @param encoding the associated encoding.
+ * @return <code>this</code>
+ * @see XMLStreamReaderImpl#setInput(InputStream, String)
+ */
+ public XMLObjectReader setInput(InputStream in, String encoding)
+ throws XMLStreamException {
+ if ((_inputStream != null) || (_reader != null))
+ throw new IllegalStateException("Reader not closed or reset");
+ _xml._reader.setInput(in, encoding);
+ _inputStream = in;
+ return this;
+ }
+
+ /**
+ * Sets the reader input source for this XML stream reader.
+ *
+ * @param in the source reader.
+ * @return <code>this</code>
+ * @see XMLStreamReaderImpl#setInput(Reader)
+ */
+ public XMLObjectReader setInput(Reader in) throws XMLStreamException {
+ if ((_inputStream != null) || (_reader != null))
+ throw new IllegalStateException("Reader not closed or reset");
+ _xml._reader.setInput(in);
+ _reader = in;
+ return this;
+ }
+
+ /**
+ * Sets the XML binding to use with this object reader.
+ *
+ * @param binding the XML binding to use.
+ * @return <code>this</code>
+ */
+ public XMLObjectReader setBinding(XMLBinding binding) {
+ _xml.setBinding(binding);
+ return this;
+ }
+
+ /**
+ * Sets the XML reference resolver to use with this object reader
+ * (the same resolver can be used accross multiple readers).
+ *
+ * @param referenceResolver the XML reference resolver.
+ * @return <code>this</code>
+ */
+ public XMLObjectReader setReferenceResolver(
+ XMLReferenceResolver referenceResolver) {
+ _xml.setReferenceResolver(referenceResolver);
+ return this;
+ }
+
+ /**
+ * Indicates if more elements can be read. This method
+ * positions the reader at the start of the
+ * next element to be read (if any).
+ *
+ * @return <code>true</code> if more element/data to be read;
+ * <code>false</code> otherwise.
+ * @see XMLFormat.InputElement#hasNext()
+ */
+ public boolean hasNext() throws XMLStreamException {
+ return _xml.hasNext();
+ }
+
+ /**
+ * Returns the object corresponding to the next element/data.
+ *
+ * @return the next nested object (can be <code>null</code>)
+ * @throws XMLStreamException if <code>hasNext() == false</code>
+ * @see XMLFormat.InputElement#getNext()
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T read() throws XMLStreamException {
+ return (T) _xml.getNext();
+ }
+
+ /**
+ * Returns the object corresponding to the next nested element only
+ * if it has the specified local name.
+ *
+ * @param name the local name of the next element.
+ * @return the next content object or <code>null</code> if the
+ * local name does not match.
+ * @see XMLFormat.InputElement#get(String)
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T read(String name) throws XMLStreamException {
+ return (T) _xml.get(name);
+ }
+
+ /**
+ * Returns the object corresponding to the next nested element only
+ * if it has the specified local name and namespace URI.
+ *
+ * @param localName the local name.
+ * @param uri the namespace URI.
+ * @return the next content object or <code>null</code> if the
+ * name/uri does not match.
+ * @see XMLFormat.InputElement#get(String, String)
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T read(String localName, String uri) throws XMLStreamException {
+ return (T) _xml.get(localName, uri);
+ }
+
+ /**
+ * Returns the object corresponding to the next nested element only
+ * if it has the specified local name; the actual object type is identified
+ * by the specified class parameter.
+ *
+ * @param name the name of the element to match.
+ * @param cls the non-abstract class identifying the object to return.
+ * @return <code>read(name, null, cls)</code>
+ */
+ public <T> T read(String name, Class<T> cls) throws XMLStreamException {
+ return _xml.get(name, cls);
+ }
+
+ /**
+ * Returns the object corresponding to the next nested element only
+ * if it has the specified local name and namespace URI; the
+ * actual object type is identified by the specified class parameter.
+ *
+ * @param localName the local name.
+ * @param uri the namespace URI.
+ * @param cls the non-abstract class identifying the object to return.
+ * @return the next content object or <code>null</code> if no match.
+ */
+ public <T> T read(String localName, String uri, Class<T> cls)
+ throws XMLStreamException {
+ return _xml.get(localName, uri, cls);
+ }
+
+ /**
+ * Closes this reader and its underlying input then {@link #reset reset}
+ * this reader for potential reuse.
+ */
+ public void close() throws XMLStreamException {
+ try {
+ if (_inputStream != null) {
+ _inputStream.close();
+ reset();
+ } else if (_reader != null) {
+ _reader.close();
+ reset();
+ }
+ } catch (IOException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+
+ /**
+ * Resets this object reader for reuse.
+ */
+ public void reset() {
+ _xml.reset();
+ _reader = null;
+ _inputStream = null;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/XMLObjectWriter.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/XMLObjectWriter.java b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLObjectWriter.java
new file mode 100644
index 0000000..7cb3d80
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLObjectWriter.java
@@ -0,0 +1,311 @@
+/*
+ * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+ * Copyright (C) 2012 - Javolution (http://javolution.org/)
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software is
+ * freely granted, provided that this notice is preserved.
+ */
+package javolution.xml;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
+
+import javolution.xml.internal.stream.XMLStreamWriterImpl;
+import javolution.xml.stream.XMLStreamException;
+import javolution.xml.stream.XMLStreamWriter;
+
+/**
+ * <p> This class takes an object and formats it to XML; the resulting
+ * XML can be deserialized using a {@link XMLObjectReader}.</p>
+ *
+ * <p> When an object is formatted, the {@link XMLFormat} of the
+ * object's class as identified by the {@link XMLBinding} is used to
+ * write its XML representation.</p>
+ *
+ * <p> Multiple objects can be written to the same XML output.
+ * For example:[code]
+ * XMLObjectWriter writer = XMLObjectWriter.newInstance(outputStream);
+ * while (true)) {
+ * Message message = ...
+ * writer.write(message, "Message", Message.class);
+ * }
+ * writer.close(); // The underlying stream is closed.
+ * [/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, September 4, 2006
+ */
+public class XMLObjectWriter {
+
+ /**
+ * Hold the xml element used when formatting.
+ */
+ private final XMLFormat.OutputElement _xml = new XMLFormat.OutputElement();
+
+ /**
+ * Holds writer if any.
+ */
+ private Writer _writer;
+
+ /**
+ * Holds input stream if any.
+ */
+ private OutputStream _outputStream;
+
+ /**
+ * Default constructor.
+ */
+ public XMLObjectWriter() {}
+
+ /**
+ * Returns a XML object writer (potentially recycled) having the specified
+ * output stream as output.
+ *
+ * @param out the output stream.
+ */
+ public static XMLObjectWriter newInstance(OutputStream out)
+ throws XMLStreamException {
+ XMLObjectWriter writer = new XMLObjectWriter();
+ writer.setOutput(out);
+ return writer;
+ }
+
+ /**
+ * Returns a XML object writer (potentially recycled) having the specified
+ * output stream/encoding as output.
+ *
+ * @param out the output stream.
+ * @param encoding the output stream encoding.
+ */
+ public static XMLObjectWriter newInstance(OutputStream out, String encoding)
+ throws XMLStreamException {
+ XMLObjectWriter writer = new XMLObjectWriter();
+ writer.setOutput(out, encoding);
+ return writer;
+ }
+
+ /**
+ * Returns a XML object writer (potentially recycled) having the specified
+ * writer as output.
+ *
+ * @param out the writer output.
+ */
+ public static XMLObjectWriter newInstance(Writer out)
+ throws XMLStreamException {
+ XMLObjectWriter writer = new XMLObjectWriter();
+ writer.setOutput(out);
+ return writer;
+ }
+
+ /**
+ * Returns the stream writer used by this object writer (it can be used
+ * to write prolog, write namespaces, etc). The stream writer is setup to
+ * automatically repair namespaces and to automatically output empty
+ * elements when a start element is immediately followed by matching end
+ * element.
+ *
+ * @return the stream writer.
+ */
+ public XMLStreamWriter getStreamWriter() {
+ return _xml._writer;
+ }
+
+ /**
+ * Sets the output stream for this XML object writer.
+ *
+ * @param out the output stream destination.
+ * @return <code>this</code>
+ * @see XMLStreamWriterImpl#setOutput(OutputStream)
+ */
+ public XMLObjectWriter setOutput(OutputStream out)
+ throws XMLStreamException {
+ if ((_outputStream != null) || (_writer != null))
+ throw new IllegalStateException("Writer not closed or reset");
+ _xml._writer.setOutput(out);
+ _outputStream = out;
+ _xml._writer.writeStartDocument();
+ return this;
+ }
+
+ /**
+ * Sets the output stream and encoding for this XML object writer.
+ *
+ * @param out the output stream destination.
+ * @param encoding the stream encoding.
+ * @return <code>this</code>
+ * @see XMLStreamWriterImpl#setOutput(OutputStream, String)
+ */
+ public XMLObjectWriter setOutput(OutputStream out, String encoding)
+ throws XMLStreamException {
+ if ((_outputStream != null) || (_writer != null))
+ throw new IllegalStateException("Writer not closed or reset");
+ _xml._writer.setOutput(out, encoding);
+ _outputStream = out;
+ _xml._writer.writeStartDocument();
+ return this;
+ }
+
+ /**
+ * Sets the output writer for this XML object writer.
+ *
+ * @param out the writer destination.
+ * @return <code>this</code>
+ * @see XMLStreamWriterImpl#setOutput(Writer)
+ */
+ public XMLObjectWriter setOutput(Writer out) throws XMLStreamException {
+ if ((_outputStream != null) || (_writer != null))
+ throw new IllegalStateException("Writer not closed or reset");
+ _xml._writer.setOutput(out);
+ _writer = out;
+ _xml._writer.writeStartDocument();
+ return this;
+ }
+
+ /**
+ * Sets the XML binding to use with this object writer.
+ *
+ * @param binding the XML binding to use.
+ * @return <code>this</code>
+ */
+ public XMLObjectWriter setBinding(XMLBinding binding) {
+ _xml.setBinding(binding);
+ return this;
+ }
+
+ /**
+ * Sets the indentation to be used by this writer (no indentation
+ * by default).
+ *
+ * @param indentation the indentation string.
+ * @return <code>this</code>
+ */
+ public XMLObjectWriter setIndentation(String indentation) {
+ _xml._writer.setIndentation(indentation);
+ return this;
+ }
+
+ /**
+ * Sets the XML reference resolver to use with this object writer
+ * (the same reference resolver can be used accross multiple writers).
+ *
+ * @param referenceResolver the XML reference resolver.
+ * @return <code>this</code>
+ */
+ public XMLObjectWriter setReferenceResolver(
+ XMLReferenceResolver referenceResolver) {
+ _xml.setReferenceResolver(referenceResolver);
+ return this;
+ }
+
+ /**
+ * Writes the specified object as an anonymous nested element of
+ * unknown type. This result in the actual type of the object being
+ * identified by the element name.
+ *
+ * @param obj the object written as nested element or <code>null</code>.
+ * @see XMLFormat.OutputElement#add(Object)
+ */
+ public void write(Object obj) throws XMLStreamException {
+ _xml.add(obj);
+ }
+
+ /**
+ * Writes the specified object as a named nested element of unknown type
+ * (<code>null</code> objects are ignored). The nested XML element
+ * may contain a class attribute identifying the object type.
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ * @param name the name of the nested element.
+ * @see XMLFormat.OutputElement#add(Object, String)
+ */
+ public void write(Object obj, String name) throws XMLStreamException {
+ _xml.add(obj, name);
+ }
+
+ /**
+ * Writes the specified object as a fully qualified nested element of
+ * unknown type (<code>null</code> objects are ignored).
+ * The nested XML element may contain a class attribute identifying
+ * the object type.
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ * @param localName the local name of the nested element.
+ * @param uri the namespace URI of the nested element.
+ * @see XMLFormat.OutputElement#add(Object, String, String)
+ */
+ public void write(Object obj, String localName, String uri)
+ throws XMLStreamException {
+ _xml.add(obj, localName, uri);
+ }
+
+ /**
+ * Writes the specified object as a named nested element of actual type
+ * known (<code>null</code> objects are ignored).
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ * @param name the name of the nested element.
+ * @param cls the non-abstract class identifying the XML format to use.
+ * @see XMLFormat.OutputElement#add(Object, String, Class)
+ */
+ public <T> void write(T obj, String name, Class<T> cls)
+ throws XMLStreamException {
+ _xml.add(obj, name, cls);
+ }
+
+ /**
+ * Writes the specified object as a fully qualified nested element of
+ * actual type known (<code>null</code> objects are ignored).
+ *
+ * @param obj the object added as nested element or <code>null</code>.
+ * @param localName the local name of the nested element.
+ * @param uri the namespace URI of the nested element.
+ * @param cls the class identifying the XML format to use.
+ * @see XMLFormat.OutputElement#add(Object, String, String, Class)
+ */
+ public <T> void write(T obj, String localName, String uri, Class<T> cls)
+ throws XMLStreamException {
+ _xml.add(obj, localName, uri, cls);
+ }
+
+ /**
+ * Flushes the output stream of this writer (automatically done
+ * when {@link #close() closing}).
+ */
+ public void flush() throws XMLStreamException {
+ _xml._writer.flush();
+ }
+
+ /**
+ * Ends document writting, closes this writer and its underlying
+ * output then {@link #reset reset} this Writer for potential reuse.
+ */
+ public void close() throws XMLStreamException {
+ try {
+ if (_outputStream != null) {
+ _xml._writer.writeEndDocument();
+ _xml._writer.close();
+ _outputStream.close();
+ reset();
+ } else if (_writer != null) {
+ _xml._writer.writeEndDocument();
+ _xml._writer.close();
+ _writer.close();
+ reset();
+ }
+
+ } catch (IOException e) {
+ throw new XMLStreamException(e);
+ }
+ }
+
+ /**
+ * Resets this object writer for reuse.
+ */
+ public void reset() {
+ _xml.reset();
+ _outputStream = null;
+ _writer = null;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/XMLReferenceResolver.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/XMLReferenceResolver.java b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLReferenceResolver.java
new file mode 100644
index 0000000..2730cf2
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLReferenceResolver.java
@@ -0,0 +1,206 @@
+/*
+ * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+ * Copyright (C) 2012 - Javolution (http://javolution.org/)
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software is
+ * freely granted, provided that this notice is preserved.
+ */
+package javolution.xml;
+
+import javolution.text.CharArray;
+import javolution.text.TextBuilder;
+import javolution.util.FastMap;
+import javolution.util.FastTable;
+import javolution.util.Index;
+import javolution.util.function.Equalities;
+import javolution.xml.stream.XMLStreamException;
+
+/**
+ * <p> This class represents a resolver for XML cross references during
+ * the marshalling/unmarshalling process.</p>
+ *
+ * <p> Instances of this class may only be shared by {@link XMLObjectReader}/
+ * {@link XMLObjectWriter} running sequentially (for cross references
+ * spawning multiple documents).</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, September 4, 2006
+ */
+public class XMLReferenceResolver {
+
+ /**
+ * Holds object to identifier (FastTable.Index) mapping.
+ */
+ private FastMap<Object, Index> _objectToId = new FastMap<Object, Index>(
+ Equalities.IDENTITY);
+
+ /**
+ * Holds the objects (index to object mapping).
+ */
+ private FastTable<Object> _idToObject = new FastTable<Object>();
+
+ /**
+ * Holds the id counter.
+ */
+ private int _counter;
+
+ /**
+ * Holds the identifier attribute name.
+ */
+ private String _idName = "id";
+
+ /**
+ * Holds the identifier attribute URI if any.
+ */
+ private String _idURI = null;
+
+ /**
+ * Holds the reference attribute name.
+ */
+ private String _refName = "ref";
+
+ /**
+ * Holds the reference attribute URI if any.
+ */
+ private String _refURI = null;
+
+ /**
+ * Default constructor.
+ */
+ public XMLReferenceResolver() {}
+
+ /**
+ * Sets the name of the identifier attribute (by default<code>"id"</code>).
+ * If the name is <code>null</code> then the identifier attribute
+ * is never read/written (which may prevent unmarshalling).
+ *
+ * @param name the name of the attribute or <code>null</code>.
+ */
+ public void setIdentifierAttribute(String name) {
+ setIdentifierAttribute(name, null);
+ }
+
+ /**
+ * Sets the local name and namespace URI of the identifier attribute.
+ *
+ * @param localName the local name of the attribute or <code>null</code>.
+ * @param uri the URI of the attribute or <code>null</code> if the attribute
+ * has no namespace URI.
+ */
+ public void setIdentifierAttribute(String localName, String uri) {
+ _idName = localName;
+ _idURI = uri;
+ }
+
+ /**
+ * Sets the name of the reference attribute (by default<code>"ref"</code>).
+ * If the name is <code>null</code> then the reference attribute
+ * is never read/written (which may prevent unmarshalling).
+ *
+ * @param name the name of the attribute or <code>null</code>.
+ */
+ public void setReferenceAttribute(String name) {
+ setReferenceAttribute(name, null);
+ }
+
+ /**
+ * Sets the local name and namespace URI of the identifier attribute.
+ *
+ * @param localName the local name of the attribute or <code>null</code>.
+ * @param uri the URI of the attribute or <code>null</code> if the attribute
+ * has no namespace URI.
+ */
+ public void setReferenceAttribute(String localName, String uri) {
+ _refName = localName;
+ _refURI = uri;
+ }
+
+ /**
+ * Writes a reference to the specified object into the specified XML
+ * element. The default implementation writes the reference into the
+ * reference attribute and for the first occurences an identifier
+ * (counter starting at 1) is written into the identifier attribute.
+ *
+ * @param obj the object for which the reference is written.
+ * @param xml the output XML element.
+ * @return <code>true</code> if a reference is written;
+ * <code>false</code> if a new identifier is written.
+ */
+ public boolean writeReference(Object obj, XMLFormat.OutputElement xml)
+ throws XMLStreamException {
+ Index id = (Index) _objectToId.get(obj);
+ if (id == null) { // New identifier.
+ id = Index.valueOf(_counter++);
+ _objectToId.put(obj, id);
+ _tmp.clear().append(id.intValue());
+ if (_idURI == null) {
+ xml.getStreamWriter().writeAttribute(_idName, _tmp);
+ } else {
+ xml.getStreamWriter().writeAttribute(_idURI, _idName, _tmp);
+ }
+ return false;
+ }
+ _tmp.clear().append(id.intValue());
+ if (_refURI == null) {
+ xml._writer.writeAttribute(_refName, _tmp);
+ } else {
+ xml._writer.writeAttribute(_refURI, _refName, _tmp);
+ }
+ return true;
+ }
+
+ private TextBuilder _tmp = new TextBuilder();
+
+ /**
+ * Reads the object referenced by the specified xml input element if any.
+ * The default implementation reads the reference attribute to retrieve
+ * the object.
+ *
+ * @param xml the input XML element.
+ * @return the referenced object or <code>null</code> if the specified
+ * XML input does not have a reference attribute.
+ */
+ public Object readReference(XMLFormat.InputElement xml)
+ throws XMLStreamException {
+ CharArray value = xml._reader.getAttributeValue(_refURI, _refName);
+ if (value == null)
+ return null;
+ int ref = value.toInt();
+ if (ref >= _idToObject.size())
+ throw new XMLStreamException("Reference: " + value + " not found");
+ return _idToObject.get(ref);
+ }
+
+ /**
+ * Creates a reference for the specified object (the identifier
+ * being specified by the input XML element).
+ * The default implementation reads the identifier attribute (if any)
+ * and associates it to the specified object.
+ *
+ * @param obj the object being referenced.
+ * @param xml the input XML element holding the reference identifier.
+ */
+ public void createReference(Object obj, XMLFormat.InputElement xml)
+ throws XMLStreamException {
+ CharArray value = xml._reader.getAttributeValue(_idURI, _idName);
+ if (value == null)
+ return;
+ int i = value.toInt();
+ if (_idToObject.size() != i)
+ throw new XMLStreamException("Identifier discontinuity detected "
+ + "(expected " + _idToObject.size() + " found " + i + ")");
+ _idToObject.add(obj);
+ }
+
+ public void reset() {
+ _idName = "id";
+ _idURI = null;
+ _refName = "ref";
+ _refURI = null;
+ _idToObject.clear();
+ _objectToId.clear();
+ _counter = 0;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/XMLSerializable.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/XMLSerializable.java b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLSerializable.java
new file mode 100644
index 0000000..46cacde
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/XMLSerializable.java
@@ -0,0 +1,47 @@
+/*
+ * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+ * Copyright (C) 2007 - Javolution (http://javolution.org/)
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software is
+ * freely granted, provided that this notice is preserved.
+ */
+package javolution.xml;
+
+import java.io.Serializable;
+
+/**
+ * <p> This interface identifies classes supporting XML serialization
+ * (XML serialization is still possible for classes not implementing this
+ * interface through dynamic {@link XMLBinding} though).</p>
+ *
+ * <p> Typically, classes implementing this interface have a protected static
+ * {@link XMLFormat} holding their default XML representation.
+ * For example:[code]
+ * public final class Complex implements XMLSerializable {
+ *
+ * // Use the cartesien form for the default XML representation.
+ * protected static final XMLFormat<Complex> XML = new XMLFormat<Complex>(Complex.class) {
+ * public Complex newInstance(Class<Complex> cls, InputElement xml) throws XMLStreamException {
+ * return Complex.valueOf(xml.getAttribute("real", 0.0),
+ * xml.getAttribute("imaginary", 0.0));
+ * }
+ * public void write(Complex complex, OutputElement xml) throws XMLStreamException {
+ * xml.setAttribute("real", complex.getReal());
+ * xml.setAttribute("imaginary", complex.getImaginary());
+ * }
+ * public void read(InputElement xml, Complex complex) {
+ * // Immutable, deserialization occurs at creation, ref. newIntance(...)
+* }
+ * };
+ * ...
+ * }[/code]</p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.2, April 15, 2007
+ */
+public interface XMLSerializable extends Serializable {
+
+ // No method. Tagging interface.
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/doc-files/xmlDataBinding.png
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/doc-files/xmlDataBinding.png b/commons/marmotta-commons/src/ext/java/javolution/xml/doc-files/xmlDataBinding.png
new file mode 100644
index 0000000..46c6efd
Binary files /dev/null and b/commons/marmotta-commons/src/ext/java/javolution/xml/doc-files/xmlDataBinding.png differ
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/internal/XMLContextImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/internal/XMLContextImpl.java b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/XMLContextImpl.java
new file mode 100644
index 0000000..d4a3f6b
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/XMLContextImpl.java
@@ -0,0 +1,151 @@
+/*
+ * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+ * Copyright (C) 2012 - Javolution (http://javolution.org/)
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software is
+ * freely granted, provided that this notice is preserved.
+ */
+package javolution.xml.internal;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import javolution.util.FastMap;
+import javolution.xml.DefaultXMLFormat;
+import javolution.xml.XMLContext;
+import javolution.xml.XMLFormat;
+import javolution.xml.stream.XMLStreamException;
+
+/**
+ * Holds the default implementation of XMLContext.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 6.0, July 21, 2013
+ */
+@SuppressWarnings("rawtypes")
+public final class XMLContextImpl extends XMLContext {
+
+ private final FastMap<Class<?>, XMLFormat<?>> formats = new FastMap<Class<?>, XMLFormat<?>>();
+
+ @Override
+ protected XMLContext inner() {
+ XMLContextImpl ctx = new XMLContextImpl();
+ ctx.formats.putAll(formats);
+ return ctx;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected <T> XMLFormat<T> searchFormat(Class<? extends T> type) {
+ XMLFormat xml = formats.get(type);
+ if (xml != null)
+ return xml;
+ DefaultXMLFormat format = type.getAnnotation(DefaultXMLFormat.class);
+ if (format != null) {
+ Class<? extends XMLFormat> formatClass = format.value();
+ try {
+ xml = formatClass.newInstance();
+ synchronized (formats) { // Required since possible concurrent use
+ // (getFormatInContext is not a configuration method).
+ formats.put(type, xml);
+ }
+ return xml;
+ } catch (Throwable ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ // Check predefined format as last resource.
+ if (Map.class.isAssignableFrom(type))
+ return MAP_XML;
+ if (Collection.class.isAssignableFrom(type))
+ return COLLECTION_XML;
+ return OBJECT_XML;
+ }
+
+ @Override
+ public <T> void setFormat(Class<? extends T> type, XMLFormat<T> format) {
+ formats.put(type, format);
+ }
+
+ /////////////////////////
+ // PREDEFINED FORMATS //
+ /////////////////////////
+ /**
+ * Holds the static XML format for <code>java.lang.Object.class</code> instances.
+ * The XML representation consists of the text representation of the object
+ * as a "value" attribute.
+ */
+ private static final XMLFormat OBJECT_XML = new XMLFormat.Default();
+
+ /**
+ * Holds the default XML representation for <code>java.util.Collection</code>
+ * instances. This representation consists of nested XML elements one for
+ * each element of the collection. The elements' order is defined by
+ * the collection iterator order. Collections are deserialized using their
+ * default constructor.
+ */
+ private static final XMLFormat COLLECTION_XML = new XMLFormat() {
+
+ @SuppressWarnings("unchecked")
+ public void read(XMLFormat.InputElement xml, Object obj)
+ throws XMLStreamException {
+ Collection collection = (Collection) obj;
+ while (xml.hasNext()) {
+ collection.add(xml.getNext());
+ }
+ }
+
+ public void write(Object obj, XMLFormat.OutputElement xml)
+ throws XMLStreamException {
+ Collection collection = (Collection) obj;
+ for (Iterator i = collection.iterator(); i.hasNext();) {
+ xml.add(i.next());
+ }
+ }
+
+ };
+
+ /**
+ * Holds the default XML representation for <code>java.util.Map</code>
+ * instances. This representation consists of key/value pair as nested
+ * XML elements. For example:[code]
+ * <javolution.util.FastMap>
+ * <Key class="java.lang.String" value="ONE"/>
+ * <Value class="java.lang.Integer" value="1"/>
+ * <Key class="java.lang.String" value="TWO"/>
+ * <Value class="java.lang.Integer" value="2"/>
+ * <Key class="java.lang.String" value="THREE"/>
+ * <Value class="java.lang.Integer" value="3"/>
+ * </javolution.util.FastMap>[/code]
+ *
+ * The elements' order is defined by the map's entries iterator order.
+ * Maps are deserialized using their default constructor.
+ */
+ private static final XMLFormat MAP_XML = new XMLFormat() {
+
+ @SuppressWarnings("unchecked")
+ public void read(XMLFormat.InputElement xml, Object obj)
+ throws XMLStreamException {
+ final Map map = (Map) obj;
+ while (xml.hasNext()) {
+ Object key = xml.get("Key");
+ Object value = xml.get("Value");
+ map.put(key, value);
+ }
+ }
+
+ public void write(Object obj, XMLFormat.OutputElement xml)
+ throws XMLStreamException {
+ final Map map = (Map) obj;
+ for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry) it.next();
+ xml.add(entry.getKey(), "Key");
+ xml.add(entry.getValue(), "Value");
+ }
+ }
+
+ };
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/AttributesImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/AttributesImpl.java b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/AttributesImpl.java
new file mode 100644
index 0000000..9953441
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/AttributesImpl.java
@@ -0,0 +1,170 @@
+package javolution.xml.internal.stream;
+
+import javolution.text.CharArray;
+import javolution.util.FastTable;
+import javolution.xml.sax.Attributes;
+
+/**
+ * This class provides the implementation of the {@link Attributes}
+ * interface for the StAX parser.
+ */
+public final class AttributesImpl implements Attributes {
+
+ /**
+ * Attribute implementation.
+ */
+ private static class AttributeImpl {
+ CharArray localName;
+ CharArray prefix; // null if no namespace URI.
+ CharArray qName;
+ CharArray value;
+ public String toString() {
+ return qName + "=" + value;
+ }
+ }
+
+ private static final CharArray CDATA = new CharArray("CDATA");
+
+ private static final CharArray EMPTY = new CharArray();
+
+ /**
+ * Holds the attributes.
+ */
+ private final FastTable<AttributeImpl> attributes = new FastTable<AttributeImpl>();
+
+ /**
+ * Holds the current number of attributes set.
+ */
+ private int length;
+
+ /**
+ * Holds the namespace stack.
+ */
+ private final NamespacesImpl namespaces;
+
+ /**
+ * Creates a list of attribute using the specified namespace stack.
+ */
+ public AttributesImpl(NamespacesImpl namespaces) {
+ this.namespaces = namespaces;
+ }
+
+ /**
+ * Adds an attribute to the end of the attribute list.
+ *
+ * @param localName the local name.
+ * @param prefix the prefix or <code>null</code> if none.
+ * @param qName the qualified (prefixed) name.
+ * @param value the attribute value.
+ */
+ public void addAttribute(CharArray localName, CharArray prefix,
+ CharArray qName, CharArray value) {
+ AttributeImpl attribute;
+ if (length >= attributes.size()) {
+ attribute = new AttributeImpl();
+ attributes.add(attribute);
+ } else {
+ attribute = attributes.get(length);
+ }
+ attribute.localName = localName;
+ attribute.prefix = prefix;
+ attribute.qName = qName;
+ attribute.value = value;
+ length++;
+ }
+
+ @Override
+ public int getIndex(CharSequence qName) {
+ for (int i = 0; i < length; i++) {
+ if (qName.equals(attributes.get(i).qName))
+ return i;
+ }
+ return -1;
+ }
+
+ @Override
+ public int getIndex(CharSequence uri, CharSequence localName) {
+ for (int i = 0; i < length; i++) {
+ AttributeImpl attribute = attributes.get(i);
+ if (localName.equals(attribute.localName)) {
+ if (attribute.prefix == null) { // No namespace URI.
+ if (uri.length() == 0)
+ return i;
+ } else { // Check if matching namespace URI.
+ if (uri.equals(namespaces.getNamespaceURI(attribute.prefix)))
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public int getLength() {
+ return length;
+ }
+
+ @Override
+ public CharArray getLocalName(int index) {
+ if ((index < 0) || (index >= length)) return null;
+ return attributes.get(index).localName;
+ }
+
+ public CharArray getPrefix(int index) {
+ if ((index < 0) || (index >= length)) return null;
+ return attributes.get(index).prefix;
+ }
+
+ @Override
+ public CharArray getQName(int index) {
+ if ((index < 0) || (index >= length)) return null;
+ return attributes.get(index).qName;
+ }
+
+ @Override
+ public CharArray getType(CharSequence qName) {
+ return (getIndex(qName) >= 0) ? CDATA : null;
+ }
+
+ @Override
+ public CharArray getType(CharSequence uri, CharSequence localName) {
+ return (getIndex(uri, localName) >= 0) ? CDATA : null;
+ }
+
+ @Override
+ public CharArray getType(int index) {
+ if ((index < 0) || (index >= length)) return null;
+ return CDATA;
+ }
+ @Override
+ public CharArray getURI(int index) {
+ if ((index < 0) || (index >= length)) return null;
+ CharArray prefix = attributes.get(index).prefix;
+ return (prefix == null) ? EMPTY : namespaces.getNamespaceURI(prefix);
+ }
+
+ @Override
+ public CharArray getValue(CharSequence qName) {
+ final int index = getIndex(qName);
+ return (index >= 0) ? attributes.get(index).value : null;
+ }
+
+ @Override
+ public CharArray getValue(CharSequence uri, CharSequence localName) {
+ final int index = getIndex(uri, localName);
+ return (index >= 0) ? attributes.get(index).value : null;
+ }
+
+ @Override
+ public CharArray getValue(int index) {
+ if ((index < 0) || (index >= length)) return null;
+ return attributes.get(index).value;
+ }
+
+ /**
+ * Clear the attribute list for reuse.
+ */
+ public void reset() {
+ length = 0;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-marmotta/blob/e43574ef/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/EntitiesImpl.java
----------------------------------------------------------------------
diff --git a/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/EntitiesImpl.java b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/EntitiesImpl.java
new file mode 100644
index 0000000..72422d3
--- /dev/null
+++ b/commons/marmotta-commons/src/ext/java/javolution/xml/internal/stream/EntitiesImpl.java
@@ -0,0 +1,155 @@
+/*
+ * Javolution - Java(TM) Solution for Real-Time and Embedded Systems
+ * Copyright (C) 2012 - Javolution (http://javolution.org/)
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software is
+ * freely granted, provided that this notice is preserved.
+ */
+package javolution.xml.internal.stream;
+
+import java.util.Map;
+
+import javolution.text.CharArray;
+import javolution.util.FastTable;
+import javolution.util.function.Function;
+import javolution.xml.stream.XMLStreamException;
+
+/**
+ * Defines entities while parsing.
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 4.0, June 16, 2006
+ */
+public final class EntitiesImpl {
+
+ /**
+ * Holds maximum length.
+ */
+ private int _maxLength = 1;
+
+ /**
+ * Holds the user defined entities mapping.
+ */
+ private Map<String, String> _entitiesMapping;
+
+ /**
+ * Default constructor.
+ */
+ EntitiesImpl() {}
+
+ /**
+ * Returns the length of the largest entity defined (default {@code 1}).
+ */
+ public int getMaxLength() {
+ return _maxLength;
+ }
+
+ /**
+ * Replaces the entity at the specified position.
+ * The five predefined XML entities "&lt;", "&gt;", "&apos;",
+ * "&quot;", "&amp;" as well as character refererences
+ * (decimal or hexadecimal) are always recognized.
+ *
+ * @param buffer the data buffer.
+ * @param start the index of entity first character (index of '&')
+ * @return the length of the replacement entity (including ';')
+ * @throws XMLStreamException if the entity is not recognized.
+ */
+ public int replaceEntity(char[] buffer, int start, int length)
+ throws XMLStreamException {
+
+ // Checks for character references.
+ if (buffer[start + 1] == '#') {
+ char c = buffer[start + 2];
+ int base = (c == 'x') ? 16 : 10;
+ int i = (c == 'x') ? 3 : 2;
+ int charValue = 0;
+ for (; i < length - 1; i++) {
+ c = buffer[start + i];
+ charValue *= base;
+ charValue += (c <= '9') ? (c - '0') : (c <= 'Z') ? c - 'A'
+ : c - 'a';
+ }
+ buffer[start] = (char) charValue;
+ return 1;
+ }
+
+ if ((buffer[start + 1] == 'l') && (buffer[start + 2] == 't')
+ && (buffer[start + 3] == ';')) {
+ buffer[start] = '<';
+ return 1;
+ }
+
+ if ((buffer[start + 1] == 'g') && (buffer[start + 2] == 't')
+ && (buffer[start + 3] == ';')) {
+ buffer[start] = '>';
+ return 1;
+ }
+
+ if ((buffer[start + 1] == 'a') && (buffer[start + 2] == 'p')
+ && (buffer[start + 3] == 'o') && (buffer[start + 4] == 's')
+ && (buffer[start + 5] == ';')) {
+ buffer[start] = '\'';
+ return 1;
+ }
+
+ if ((buffer[start + 1] == 'q') && (buffer[start + 2] == 'u')
+ && (buffer[start + 3] == 'o') && (buffer[start + 4] == 't')
+ && (buffer[start + 5] == ';')) {
+ buffer[start] = '"';
+ return 1;
+ }
+
+ if ((buffer[start + 1] == 'a') && (buffer[start + 2] == 'm')
+ && (buffer[start + 3] == 'p') && (buffer[start + 4] == ';')) {
+ buffer[start] = '&';
+ return 1;
+ }
+
+ // Searches user defined entities.
+ _tmp.setArray(buffer, start + 1, length - 2);
+ CharSequence replacementText = (_entitiesMapping != null) ? _entitiesMapping
+ .get(_tmp) : null;
+ if (replacementText == null)
+ throw new XMLStreamException("Entity " + _tmp + " not recognized");
+ int replacementTextLength = replacementText.length();
+ for (int i = 0; i < replacementTextLength; i++) {
+ buffer[start + i] = replacementText.charAt(i);
+ }
+ return replacementTextLength;
+ }
+
+ private CharArray _tmp = new CharArray();
+
+ /**
+ * Sets the current custom entity mapping. For example: {@code
+ * new FastMap().put("copy", "©")} to define the copyright entity.
+ */
+ public void setEntitiesMapping(Map<String, String> entityToReplacementText) {
+ FastTable<String> values = new FastTable<String>();
+ values.addAll(entityToReplacementText.values());
+ _maxLength = values.mapped(new Function<CharSequence, Integer>() {
+
+ @Override
+ public Integer apply(CharSequence csq) {
+ return csq.length();
+ }}).max();
+
+ _entitiesMapping = entityToReplacementText;
+ }
+
+ /**
+ * Returns the custom entity mapping or {@code null} if none.
+ */
+ public Map<String, String> getEntitiesMapping() {
+ return _entitiesMapping;
+ }
+
+ // Implements Reusable.
+ public void reset() {
+ _maxLength = 1;
+ _entitiesMapping = null;
+ }
+
+}