/*
* This software is Copyright 2005,2006,2007,2008 Langdale Consultants.
* Langdale Consultants can be contacted at: http://www.langdale.com.au
*/
package au.com.langdale.sax;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Enumeration;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.NamespaceSupport;
public abstract class AbstractReader extends XMLReaderBase {
/** Optimisation provides a single copy of the empty atts */
private final Attributes empty = new AttributesImpl();
/** The top of the current element stack */
private Element top = null;
protected Element getTop() {
return top;
}
/** The current namespace bindings */
NamespaceSupport spaces = new NamespaceSupport();
/**
* Convenience class to generate an element from a given word or the current
* token.
*/
protected class Element {
private Element parent;
private String type;
private boolean committed = false;
private AttributesImpl atts = null;
private int depth = 0;
private boolean printing = false;
private String[] parts = new String[3];
private String[] attr_parts;
public Element(String type, String namespace) throws SAXException {
this(type);
spaces.declarePrefix("", namespace);
output.startPrefixMapping("", namespace);
}
public Element(String type) throws SAXException {
parent = top;
top = this;
this.type = type;
spaces.pushContext();
if (parent != null) {
parent.commit();
depth = parent.depth + 1;
}
}
public void commit() throws SAXException {
if (!committed) {
print("+" + type);
Attributes passed = atts != null ? atts : empty;
if (spaces.processName(type, parts, false) == null)
throw new SAXException("undeclared namespace prefix: "
+ type);
output.startElement(parts[0], parts[1], parts[2], passed);
committed = true;
}
}
public void close() throws SAXException {
commit();
output.endElement(parts[0], parts[1], parts[2]);
Enumeration ix = spaces.getDeclaredPrefixes();
while (ix.hasMoreElements()) {
String prefix = (String) ix.nextElement();
output.endPrefixMapping(prefix);
}
print("-" + type);
if (top != this) {
throw new SAXException("internal error: elements out of order");
}
if (depth == 0) {
print("the end");
}
top = parent;
spaces.popContext();
}
private void declare(String name, String value) throws SAXException {
int colon = name.indexOf(':');
if (colon == -1) {
spaces.declarePrefix("", value);
output.startPrefixMapping("", value);
} else {
String prefix = name.substring(colon + 1);
spaces.declarePrefix(prefix, value);
output.startPrefixMapping(prefix, value);
}
}
public void set(String name, String value) throws SAXException {
if (committed)
throw new SAXException("attribute out of order");
if (name.startsWith("xmlns")) {
declare(name, value);
return;
}
if (atts == null) {
atts = new AttributesImpl();
attr_parts = new String[3];
}
if (spaces.processName(name, attr_parts, true) == null)
throw new SAXException("undeclared namespace prefix in: "
+ name);
atts.addAttribute(attr_parts[0], attr_parts[1], attr_parts[2],
"CDATA", value);
}
public void set(String name, StringBuffer value) throws SAXException {
set(name, value.toString());
}
public void append(String text) throws SAXException {
commit();
char[] ch = new char[text.length()];
text.getChars(0, text.length(), ch, 0);
output.characters(ch, 0, text.length());
}
public void append(StringBuffer text) throws SAXException {
commit();
char[] ch = new char[text.length()];
text.getChars(0, text.length(), ch, 0);
output.characters(ch, 0, text.length());
}
public void print(String message) {
if (printing) {
for (int i = 0; i < depth; i++)
System.out.print(" ");
System.out.println(message);
}
}
}
public void write(OutputStream ostream) throws TransformerException {
Result result = new StreamResult(ostream);
Source source = new SAXSource(this, new InputSource());
TransformerFactory.newInstance().newTransformer().transform(source,
result);
}
public void write(String filename) throws TransformerException, IOException {
BufferedOutputStream ostream = new BufferedOutputStream( new FileOutputStream(filename));
write(ostream);
ostream.close();
}
@Override
protected void parse() throws SAXException, IOException {
output.startDocument();
emit();
output.endDocument();
}
protected abstract void emit() throws SAXException;
}