package org.anodyneos.xp;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
public final class XpOutput {
//public static final int XML_MODE = 0;
//public static final int RAW_MODE = 1;
//private int mode = XML_MODE;
private final XpContentHandler ch;
/*
public XpOutput(XpContentHandler ch) {
this.ch = ch;
}
public XpOutput(XpContentHandler ch, int mode) {
this.ch = ch;
setMode(mode);
}
*/
public XpOutput(ContentHandler ch) {
this.ch = XpContentHandlerFactory.getDefaultFactory().getXpContentHandler(ch);
}
public XpOutput(ContentHandler ch, boolean namespacePrefixes) {
this.ch = XpContentHandlerFactory.getDefaultFactory().getXpContentHandler(ch, namespacePrefixes);
}
/*
public XpOutput(ContentHandler ch, int mode) {
this.ch = XpContentHandlerFactory.getDefaultFactory().getXpContentHandler(ch);
setMode(mode);
}
*/
/*
private void setMode(int mode) {
if (mode < 0 || mode > 1) {
throw new IllegalArgumentException("Invalid mode: " + mode);
} else {
this.mode = mode;
}
}
*/
public XpContentHandler getXpContentHandler() {
return ch;
}
public void addAttribute(String uri, String qName, String value)
throws SAXException {
ch.addAttribute(uri, qName, value);
}
public void endElement(String uri, String qName) throws SAXException {
ch.endElement(uri, qName);
}
public void startElement(String uri, String qName) throws SAXException {
ch.startElement(uri, qName);
}
public static final char CR = '\r';
public static final char LF = '\n';
/**
* Writes text content to the result XML document with proper CRLF conversions.
*
* @param ch
* @param start
* @param length
* @throws SAXException
*/
public void write(char[] ch, int start, int length) throws SAXException {
if(null == ch || length < 1) {
return;
}
/*
if (RAW_MODE == mode) {
// perform no CRLF translation
this.ch.characters(ch, start, length);
} else {
*/
// translate CRLF for XML spec
int lastSent = start - 1;
boolean lastWasCR = false;
char current;
// send out one chunk at a time
for (int i = start; i < start + length; i++) {
current = ch[i];
if (current == CR) {
if (lastWasCR) {
// two CR's back-to-back, send LF for the last one
this.ch.characters(LF);
}
lastWasCR = true;
// we won't be outputing this CR, so send previous characters now,
// but not if length == 0
if (! (lastSent + 1 == i)) {
this.ch.characters(ch, lastSent + 1, i - lastSent - 1);
}
lastSent = i;
} else if (lastWasCR && current == LF) {
// the last CR matches this LF; lets keep the LF but dump the CR
lastWasCR = false;
assert lastSent == i - 1;
} else if (lastWasCR) {
// last was a CR that needs to be a LF
lastWasCR = false;
this.ch.characters(LF);
assert lastSent == i - 1;
}
}
if (lastWasCR) {
this.ch.characters(LF);
assert lastSent == start + length - 1;
} else if (lastSent + 1 < start + length) {
this.ch.characters(ch, lastSent + 1, length - (lastSent - start + 1));
}
}
/**
* Writes text content to the result XML document with proper CRLF conversions.
*
* @param s
* @throws SAXException
*/
public void write(String s) throws SAXException {
if (null != s) {
write(s.toCharArray(), 0, s.length());
} else {
// no CRLF conversion needed, use this.ch
this.ch.characters((String) null);
}
}
/**
* Writes text content to the result XML document with proper CRLF conversions.
*
* @param x
* @throws SAXException
*/
public void write(Object x) throws SAXException {
if (null != x) {
write(x.toString());
} else {
write((String) null);
}
}
public void write(char x) throws SAXException {
this.ch.characters(x);
}
public void write(byte x) throws SAXException {
this.ch.characters(x);
}
public void write(boolean x) throws SAXException {
this.ch.characters(x);
}
public void write(int x) throws SAXException {
this.ch.characters(x);
}
public void write(long x) throws SAXException {
this.ch.characters(x);
}
public void write(float x) throws SAXException {
this.ch.characters(x);
}
public void write(double x) throws SAXException {
this.ch.characters(x);
}
}