/* * Javolution - Java(TM) Solution for Real-Time and Embedded Systems * Copyright (C) 2006 - 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.lang.CharSequence; import javolution.lang.Reflection; import javolution.text.CharArray; import javolution.text.Text; import javolution.text.TextBuilder; import javolution.text.TextFormat; import javolution.xml.sax.Attributes; import javolution.xml.stream.XMLStreamException; import javolution.xml.stream.XMLStreamReader; import javolution.xml.stream.XMLStreamReaderImpl; import javolution.xml.stream.XMLStreamWriter; import javolution.xml.stream.XMLStreamWriterImpl; /** * <p> This class represents the format base class for XML serialization and * deserialization.</p> * * <p> Application classes typically define a default XML format for their * instances using protected static {@link XMLFormat} class members. * Formats are inherited by sub-classes. For example:[code] * * 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. * protected static final XMLFormat<Graphic> GRAPHIC_XML = new XMLFormat<Graphic>(Graphic.class) { * 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 text format is * {@link TextFormat#getInstance known} 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"; /** * Holds the class associated to this format (static instances) * or <code>null</code> if format is unbound. */ private final Class <T> _class; /** * Defines the default XML format bound to the specified class. * If the specified class is <code>null</code> then the format is unbound * (unbound formats are used by custom {@link XMLBinding binding} instances). * The static binding is unique and can only be overriden by custom * {@link XMLBinding}. For example:[code] * // Overrides default binding for java.util.Collection. * class MyBinding extends XMLBinding { * XMLFormat<Collection> collectionXML = new XMLFormat<Collection>(null) { ... }; // Unbound. * public XMLFormat getFormat(Class cls) { * if (Collection.isAssignableFrom(cls)) { * return collectionXML; // Overrides default XML format. * } else { * return super.getFormat(cls); * } * } * }[/code] * * @param forClass the root class/interface to associate to this XML format * or <code>null</code> if this format is not bound. * @throws IllegalArgumentException if a XMLFormat is already bound to * the specified class. */ protected XMLFormat(Class <T> forClass) { _class = forClass; if (forClass == null) return; // Dynamic format. Reflection.getInstance().setField(this, forClass, XMLFormat.class); } /** * <p> Returns the default format for the specified class/interface. * If there no direct mapping for the specified class, the mapping * for the specified class interfaces is searched, if none is found * the mapping for the parents classes is searched, if still none is * found the format for <code>java.lang.Object</code> is returned.</p> * * <p> A default xml format exists for the following predefined types: * <code><ul> * <li>java.lang.Object</li> * <li>java.util.Collection</li> * <li>java.util.Map</li> * </ul></code> * The default XML representation (java.lang.Object) consists of the * of a "value" attribute holding its textual representation * (see {@link TextFormat#getInstance}).</p> * * @return the class/interface bound to this format. */ public static <T> XMLFormat <T> getInstance(Class <? extends T> forClass) { XMLFormat objectFormat = XMLBinding.OBJECT_XML; // Also forces initialization or XMLBinding. XMLFormat xmlFormat = (XMLFormat) Reflection.getInstance().getField(forClass, XMLFormat.class, true); return (xmlFormat != null) ? xmlFormat : objectFormat; } /** * Returns the class/interface statically bound to this format or * <code>null</code> if none. * * @return the class/interface bound to this format. */ public final Class <T> getBoundClass() { return _class; } /** * 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 <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; /** * Returns textual information about this format. * * @return this format textual information. */ public String toString() { Class boundClass = getBoundClass(); return (boundClass != null) ? "Default XMLFormat for " + boundClass.getName() : "Dynamic XMLtFormat (" + this.hashCode() + ")"; } /** * This class represents an input XML element (unmarshalling). */ 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 ( T ) 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 ( T ) 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 ( T ) 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 ( T ) 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 ( T ) 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. private Object 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 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, toCsq(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. The default value * {@link javolution.text.TextFormat#getInstance TextFormat} is * used to parse the attribute 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 = TextFormat.getInstance(type); if (!format.isParsingSupported()) throw new XMLStreamException("No TextFormat instance 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). */ 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(toCsq(NULL)); return; } // Writes start element. Class cls = obj.getClass(); _binding.writeClass(obj.getClass(), _writer, false); // Checks if reference written. XMLFormat xmlFormat = _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(toCsq(name)); // Writes class attribute. Class cls = obj.getClass(); _binding.writeClass(cls, _writer, true); // Checks if reference written. XMLFormat xmlFormat = _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(toCsq(uri), toCsq(localName)); // Writes class attribute. Class cls = obj.getClass(); _binding.writeClass(cls, _writer, true); // Checks if reference written. XMLFormat xmlFormat = _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(toCsq(name)); // Checks if reference written. XMLFormat xmlFormat = _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(toCsq(uri), toCsq(localName)); // Checks if reference written. XMLFormat xmlFormat = _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(toCsq(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(toCsq(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(toCsq(name), toCsq(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#getInstance TextFormat}. * * @param name the name of the attribute. * @param value the <code>Boolean</code> 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; Class type = value.getClass(); TextFormat format = TextFormat.getInstance(type); setAttribute(name, (TextBuilder) format.format(value, _tmpTextBuilder.clear())); } // 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; } } // For J2ME Compatibility. private static CharSequence toCsq(Object str) { /**/ if (true) return (CharSequence) str; /**/ return str == null ? null : Text.valueOf(str); } }