package gnu.xml.dom.ls;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.xml.XMLConstants;
import org.w3c.dom.Attr;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.Entity;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.xml.sax.Attributes;
import org.xml.sax.DTDHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.ext.Attributes2;
import org.xml.sax.ext.DeclHandler;
import org.xml.sax.ext.LexicalHandler;
import gnu.xml.aelfred2.ContentHandler2;
import gnu.xml.dom.DomAttr;
import gnu.xml.dom.DomDocument;
import gnu.xml.dom.DomDoctype;
class SAXEventSink
implements ContentHandler2, LexicalHandler, DTDHandler, DeclHandler
{
private static final String XMLNS_URI = XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
private static final String XMLNS_PREFIX = XMLConstants.XMLNS_ATTRIBUTE;
boolean namespaceAware;
boolean ignoreWhitespace;
boolean expandEntityReferences;
boolean ignoreComments;
boolean coalescing;
DomDocument doc; Node ctx; LinkedList entityCtx; List pending; Locator locator;
boolean inCDATA;
boolean inDTD;
boolean interrupted;
void interrupt()
{
interrupted = true;
}
public void setDocumentLocator(Locator locator)
{
this.locator = locator;
}
public void startDocument()
throws SAXException
{
if (namespaceAware)
{
pending = new LinkedList();
}
doc = new DomDocument();
doc.setStrictErrorChecking(false);
doc.setBuilding(true);
ctx = doc;
}
public void xmlDecl(String version, String encoding, boolean standalone,
String inputEncoding)
throws SAXException
{
if (interrupted)
{
return;
}
doc.setXmlVersion(version);
doc.setXmlEncoding(encoding);
doc.setXmlStandalone(standalone);
doc.setInputEncoding(inputEncoding);
}
public void endDocument()
throws SAXException
{
doc.setStrictErrorChecking(true);
doc.setBuilding(false);
DomDoctype doctype = (DomDoctype) doc.getDoctype();
if (doctype != null)
{
doctype.makeReadonly();
}
ctx = null;
locator = null;
}
public void startPrefixMapping(String prefix, String uri)
throws SAXException
{
if (namespaceAware)
{
String nsName = (prefix != null && prefix.length() > 0) ?
XMLNS_PREFIX + ":" + prefix : XMLNS_PREFIX;
DomAttr ns = (DomAttr) doc.createAttributeNS(XMLNS_URI, nsName);
ns.setNodeValue(uri);
if (ctx.getNodeType() == Node.ATTRIBUTE_NODE)
{
Node target = ((Attr) ctx).getOwnerElement();
target.getAttributes().setNamedItemNS(ns);
}
else
{
pending.add(ns);
}
}
}
public void endPrefixMapping(String prefix)
throws SAXException
{
}
public void startElement(String uri, String localName, String qName,
Attributes atts)
throws SAXException
{
if (interrupted)
{
return;
}
Element element = createElement(uri, localName, qName, atts);
ctx.appendChild(element);
ctx = element;
}
protected Element createElement(String uri, String localName, String qName,
Attributes atts)
throws SAXException
{
Element element = namespaceAware ?
doc.createElementNS(uri, qName) :
doc.createElement(qName);
NamedNodeMap attrs = element.getAttributes();
if (namespaceAware && !pending.isEmpty())
{
for (Iterator i = pending.iterator(); i.hasNext(); )
{
Node ns = (Node) i.next();
attrs.setNamedItemNS(ns);
}
pending.clear();
}
int len = atts.getLength();
for (int i = 0; i < len; i++)
{
Attr attr = createAttr(atts, i);
if (attr != null)
{
if (namespaceAware)
{
attrs.setNamedItemNS(attr);
}
else
{
attrs.setNamedItem(attr);
}
}
}
return element;
}
protected Attr createAttr(Attributes atts, int index)
{
DomAttr attr;
if (namespaceAware)
{
String a_uri = atts.getURI(index);
String a_qName = atts.getQName(index);
attr = (DomAttr) doc.createAttributeNS(a_uri, a_qName);
}
else
{
String a_qName = atts.getQName(index);
attr = (DomAttr) doc.createAttribute(a_qName);
}
attr.setNodeValue(atts.getValue(index));
if (atts instanceof Attributes2)
{
Attributes2 atts2 = (Attributes2) atts;
attr.setSpecified(atts2.isSpecified(index));
}
return attr;
}
public void endElement(String uri, String localName, String qName)
throws SAXException
{
if (interrupted)
{
return;
}
if (namespaceAware)
{
pending.clear();
}
ctx = ctx.getParentNode();
}
public void characters(char[] c, int off, int len)
throws SAXException
{
if (interrupted)
{
return;
}
ctx.appendChild(createText(c, off, len));
}
protected Text createText(char[] c, int off, int len)
throws SAXException
{
Text text = (inCDATA && !coalescing) ?
doc.createCDATASection(new String(c, off, len)) :
doc.createTextNode(new String(c, off, len));
return text;
}
public void ignorableWhitespace(char[] c, int off, int len)
throws SAXException
{
if (interrupted)
{
return;
}
if (!ignoreWhitespace)
{
characters(c, off, len);
}
}
public void processingInstruction(String target, String data)
throws SAXException
{
if (interrupted)
{
return;
}
if (!inDTD)
{
Node pi = createProcessingInstruction(target, data);
ctx.appendChild(pi);
}
}
protected Node createProcessingInstruction(String target, String data)
{
return doc.createProcessingInstruction(target, data);
}
public void skippedEntity(String name)
throws SAXException
{
}
public void startDTD(String name, String publicId, String systemId)
throws SAXException
{
if (interrupted)
{
return;
}
Node doctype = createDocumentType(name, publicId, systemId);
doc.appendChild(doctype);
ctx = doctype;
inDTD = true;
}
protected Node createDocumentType(String name, String publicId,
String systemId)
{
return new DomDoctype(doc, name, publicId, systemId);
}
public void endDTD()
throws SAXException
{
if (interrupted)
{
return;
}
inDTD = false;
ctx = ctx.getParentNode();
}
public void startEntity(String name)
throws SAXException
{
DocumentType doctype = doc.getDoctype();
if (doctype == null)
{
throw new SAXException("SAX parser error: " +
"reference to entity in undeclared doctype");
}
if ("[dtd]".equals(name) || name.charAt(0) == '%')
{
ctx = doctype;
return;
}
if ("lt".equals(name) ||
"gt".equals(name) ||
"amp".equals(name) ||
"apos".equals(name) ||
"quot".equals(name))
{
return;
}
NamedNodeMap entities = doctype.getEntities();
Entity entity = (Entity) entities.getNamedItem(name);
if (entity == null)
{
throw new SAXException("SAX parser error: " +
"reference to undeclared entity: " + name);
}
pushEntity(entity);
}
public void endEntity(String name)
throws SAXException
{
if ("[dtd]".equals(name) || name.charAt(0) == '%')
{
return;
}
if ("lt".equals(name) ||
"gt".equals(name) ||
"amp".equals(name) ||
"apos".equals(name) ||
"quot".equals(name))
{
return;
}
Entity entity = popEntity();
if (expandEntityReferences)
{
for (Node child = entity.getFirstChild(); child != null;
child = child.getNextSibling())
{
ctx.appendChild(child);
}
}
else
{
Node entityReference = doc.createEntityReference(name);
ctx.appendChild(entityReference);
}
}
void pushEntity(Node entity)
{
if (entityCtx == null)
{
entityCtx = new LinkedList();
}
entityCtx.addLast(ctx);
ctx = entity;
}
Entity popEntity()
{
Entity ret = (Entity) ctx;
ctx = (Node) entityCtx.removeLast();
return ret;
}
public void startCDATA()
throws SAXException
{
inCDATA = true;
}
public void endCDATA()
throws SAXException
{
inCDATA = false;
}
public void comment(char[] c, int off, int len)
throws SAXException
{
if (interrupted)
{
return;
}
if (!inDTD)
{
Node comment = createComment(c, off, len);
ctx.appendChild(comment);
}
}
protected Node createComment(char[] c, int off, int len)
{
return doc.createComment(new String(c, off, len));
}
public void notationDecl(String name, String publicId, String systemId)
throws SAXException
{
if (interrupted)
{
return;
}
DomDoctype doctype = (DomDoctype) ctx;
doctype.declareNotation(name, publicId, systemId);
}
public void unparsedEntityDecl(String name, String publicId, String systemId,
String notationName)
throws SAXException
{
if (interrupted)
{
return;
}
DomDoctype doctype = (DomDoctype) ctx;
Entity entity = doctype.declareEntity(name, publicId, systemId,
notationName);
}
public void elementDecl(String name, String model)
throws SAXException
{
if (interrupted)
{
return;
}
if (!(ctx instanceof DomDoctype))
{
return;
}
DomDoctype doctype = (DomDoctype) ctx;
doctype.elementDecl(name, model);
}
public void attributeDecl(String eName, String aName, String type,
String mode, String value)
throws SAXException
{
if (interrupted)
{
return;
}
DomDoctype doctype = (DomDoctype) ctx;
doctype.attributeDecl(eName, aName, type, mode, value);
}
public void internalEntityDecl(String name, String value)
throws SAXException
{
if (interrupted)
{
return;
}
DomDoctype doctype = (DomDoctype) ctx;
Entity entity = doctype.declareEntity(name, null, null, null);
if (entity != null)
{
Node text = doc.createTextNode(value);
entity.appendChild(text);
}
}
public void externalEntityDecl(String name, String publicId, String systemId)
throws SAXException
{
if (interrupted)
{
return;
}
DomDoctype doctype = (DomDoctype) ctx;
Entity entity = doctype.declareEntity(name, publicId, systemId, null);
}
}