| ElementSerializer.java |
/*
* $Id: ElementSerializer.java,v 1.36 2010/09/29 20:04:51 agoubard Exp $
*
* See the COPYRIGHT file for redistribution and use restrictions.
*/
package org.xins.common.xml;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.xins.common.MandatoryArgumentChecker;
import org.xins.common.Utils;
import org.znerd.xmlenc.XMLOutputter;
/**
* Serializer that takes an <code>Element</code> and converts it to an XML
* string.
*
* <p>This class is not thread-safe. It should only be used on one thread at a
* time.
*
* @version $Revision: 1.36 $ $Date: 2010/09/29 20:04:51 $
* @author <a href="mailto:anthony.goubard@japplis.com">Anthony Goubard</a>
* @author <a href="mailto:ernst@ernstdehaan.com">Ernst de Haan</a>
*
* @since XINS 1.1.0
* @deprecated since XINS 3.0. Use {@link org.w3c.dom.Element}
*/
@Deprecated
public final class ElementSerializer {
/**
* Lock object that is synchronized on when reading or writing
* <code>_inUse</code>.
*/
private final Object _lock;
/**
* Flag that indicates whether this serializer is currently in use. It may
* only be used by one thread at a time.
*/
private boolean _inUse;
/**
* Constructs a new <code>ElementSerializer</code>.
*/
public ElementSerializer() {
_lock = new Object();
}
/**
* Serializes the element to XML. This method is not reentrant. Hence, it
* should only be used from a single thread.
*
* @param element
* the element to serialize, cannot be <code>null</code>.
*
* @return
* an XML document that represents <code>element</code>, never
* <code>null</code>.
*
* @throws IllegalArgumentException
* if <code>element == null</code>.
*/
public String serialize(Element element)
throws IllegalArgumentException {
synchronized (_lock) {
// Make sure this serializer is not yet in use
if (_inUse) {
String detail = "ElementSerializer instance already in use.";
throw Utils.logProgrammingError(detail);
}
// Lock this serializer
_inUse = true;
}
// Check argument
MandatoryArgumentChecker.check("element", element);
// Create an XMLOutputter
Writer fsw = new StringWriter(512);
XMLOutputter out;
final String ENCODING = "UTF-8";
try {
out = new XMLOutputter(fsw, ENCODING);
} catch (UnsupportedEncodingException uee) {
String message = "Expected XMLOutputter to support encoding \"" + ENCODING + "\".";
throw Utils.logProgrammingError(message, uee);
}
// XXX: Allow output of declaration to be configured?
// Output the XML that represents the Element
try {
output(out, element);
// I/O errors should not happen on a StringWriter
} catch (IOException exception) {
throw Utils.logProgrammingError(exception);
} finally {
_inUse = false;
}
String xml = fsw.toString();
return xml;
}
/**
* Generates XML for the specified <code>Element</code>.
*
* @param out
* the {@link XMLOutputter} to use, cannot be <code>null</code>.
*
* @param element
* the {@link Element} object to convert to XML, cannot be
* <code>null</code>.
*
* @throws NullPointerException
* if <code>out == null || element == null</code>.
*
* @throws IOException
* if there is an I/O error.
*/
public void output(XMLOutputter out, Element element)
throws NullPointerException, IOException {
String namespacePrefix = element.getNamespacePrefix();
String namespaceURI = element.getNamespaceURI();
String localName = element.getLocalName();
Map namespaces = new HashMap();
// Write an element with namespace
if (namespacePrefix != null) {
out.startTag(namespacePrefix + ':' + localName);
// Write an element without namespace
} else {
out.startTag(localName);
}
if (namespaceURI != null) {
// Associate the namespace with the prefix in the result XML
if (namespacePrefix == null) {
out.attribute("xmlns", namespaceURI);
namespaces.put("", namespaceURI);
} else {
out.attribute("xmlns:" + namespacePrefix, namespaceURI);
namespaces.put(namespacePrefix, namespaceURI);
}
}
// Loop through all attributes
Map attributes = element.getAttributeMap();
Iterator entries = attributes.entrySet().iterator();
while (entries.hasNext()) {
// Get the next Map.Entry from the iterator
Map.Entry entry = (Map.Entry) entries.next();
// Get the namespace, local name and value
Element.QualifiedName qn = (Element.QualifiedName) entry.getKey();
String attrNamespaceURI = qn.getNamespaceURI();
String attrLocalName = qn.getLocalName();
String attrNamespacePrefix = qn.getNamespacePrefix();
String attrValue = (String) entry.getValue();
// Do not write the attribute if no value or it is the namespace URI.
if (attrValue != null &&
(!"xmlns".equals(attrNamespacePrefix) || !attrLocalName.equals(namespacePrefix))) {
// Write the attribute with prefix
if (attrNamespacePrefix != null) {
out.attribute(attrNamespacePrefix + ':' + attrLocalName, attrValue);
// Write an attribute without prefix
} else {
out.attribute(attrLocalName, attrValue);
}
// Write the attribute namespace
if (attrNamespaceURI != null) {
// Associate the namespace with the prefix in the result XML
if (attrNamespacePrefix == null && !namespaces.containsKey("")) {
out.attribute("xmlns", attrNamespaceURI);
namespaces.put("", namespaceURI);
} else if (!namespaces.containsKey(attrNamespacePrefix)) {
out.attribute("xmlns:" + attrNamespacePrefix, attrNamespaceURI);
namespaces.put(attrNamespacePrefix, namespaceURI);
}
}
}
}
// Process all contained elements
List content = element.getChildElements();
int count = content.size();
for (int i = 0; i < count; i++) {
Object o = content.get(i);
output(out, (Element) o);
}
// Output contained PCDATA
if (element.getText() != null) {
out.pcdata(element.getText());
}
// End the tag
out.endTag();
}
}