package com.skaringa.javaxml.handler.sax;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import com.skaringa.javaxml.PropertyKeys;
import com.skaringa.javaxml.SerializerException;
import com.skaringa.javaxml.handler.AbstractDocumentOutputHandler;
import com.skaringa.javaxml.handler.AttrImpl;
import com.skaringa.javaxml.handler.DocumentOutputHandlerInterface;
import com.skaringa.javaxml.impl.NSConstants;
import com.skaringa.javaxml.impl.PropertyHelper;
import com.skaringa.util.Log;
/**
* A concrete DocumentOutputHandlerInterface.
* It writes the output events to a SAX content handler.
* It is used for serialization of Java objects into XML documents.
*/
public final class SAXOutputHandler
extends AbstractDocumentOutputHandler
implements DocumentOutputHandlerInterface {
private ContentHandler _ch;
private boolean _isRootElement;
/**
* Construct a new SAXOutputHandler.
* @param ch The SAX content handler which gets the output events.
*/
public SAXOutputHandler(ContentHandler ch) {
_ch = ch;
}
/**
* @see DocumentOutputHandlerInterface#startDocument()
*/
public void startDocument() throws SerializerException {
Log.debug("startDocument");
try {
_ch.startDocument();
_isRootElement = true;
}
catch (SAXException e) {
Log.error(e);
throw new SerializerException(e.toString());
}
}
/**
* @see DocumentOutputHandlerInterface#endDocument()
*/
public void endDocument() throws SerializerException {
Log.debug("endDocument");
try {
_ch.endDocument();
}
catch (SAXException e) {
Log.error(e);
throw new SerializerException(e.toString());
}
}
/**
* @see DocumentOutputHandlerInterface#startElement(String, Attributes)
*/
public void startElement(String name, Attributes attrs)
throws SerializerException {
try {
if (_isRootElement) {
_isRootElement = false;
boolean omitXsi =
PropertyHelper.parseBoolean(
getProperties(),
PropertyKeys.OMIT_XSI_TYPE);
boolean omitNil =
PropertyHelper.parseBoolean(
getProperties(),
PropertyKeys.OMIT_XSI_NIL);
if (!(omitXsi && omitNil) || name.equals("xsd:schema")) {
// write namespace declarations
_ch.startPrefixMapping(
NSConstants.SCHEMA_INSTANCE_NS_PREFIX,
NSConstants.SCHEMA_INSTANCE_NS_NAME);
_ch.startPrefixMapping(
NSConstants.SCHEMA_NS_PREFIX,
NSConstants.SCHEMA_NS_NAME);
if (_ch.getClass().getName().indexOf("saxon") == -1) {
attrs = appendNamespaceDeclarations(name, attrs);
}
}
}
if (Log.isDebugEnabled()) {
Log.debug(name + " " + attrs.toString());
}
int p = name.indexOf(':');
if (p > -1) {
_ch.startElement(
name.substring(0, p - 1),
name.substring(p + 1),
name,
attrs);
}
else {
_ch.startElement("", name, name, attrs);
}
}
catch (SAXException e) {
Log.error(e);
throw new SerializerException(e.toString());
}
}
/**
* @see DocumentOutputHandlerInterface#startElement(String)
*/
public void startElement(String name) throws SerializerException {
Attributes attrs = new AttrImpl();
startElement(name, attrs);
}
/**
* @see DocumentOutputHandlerInterface#appendText(String)
*/
public void appendText(String text) throws SerializerException {
Log.debug(text);
try {
char[] c = text.toCharArray();
int writepos = 0;
for (int i = 0; i < c.length; ++i) {
if (Character.isISOControl(c[i])) {
_ch.characters(c, writepos, i - writepos);
_ch.processingInstruction("char", Integer.toHexString(c[i]));
writepos = i + 1;
}
}
_ch.characters(c, writepos, c.length - writepos);
}
catch (SAXException e) {
Log.error(e);
throw new SerializerException(e.toString());
}
}
/**
* @see DocumentOutputHandlerInterface#endElement(String)
*/
public void endElement(String name) throws SerializerException {
Log.debug(name);
try {
int p = name.indexOf(':');
if (p > -1) {
_ch.endElement(name.substring(0, p - 1), name.substring(p + 1), name);
}
else {
_ch.endElement("", name, name);
}
}
catch (SAXException e) {
Log.error(e);
throw new SerializerException(e.toString());
}
}
}