/*
* eXist Open Source Native XML Database
* Copyright (C) 2001-06 Wolfgang M. Meier
* wolfgang@exist-db.org
* http://exist.sourceforge.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id$
*/
package org.exist.memtree;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.exist.dom.NodeProxy;
import org.exist.dom.QName;
import org.exist.dom.StoredNode;
import org.exist.util.serializer.AttrList;
import org.exist.util.serializer.Receiver;
import org.exist.xquery.Constants;
import org.exist.xquery.XQueryContext;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
/**
* Builds an in-memory DOM tree from SAX {@link org.exist.util.serializer.Receiver}
* events.
*
* @author Wolfgang <wolfgang@exist-db.org>
*/
public class DocumentBuilderReceiver implements ContentHandler, LexicalHandler, Receiver {
private MemTreeBuilder builder = null;
private Map namespaces = null;
private boolean explicitNSDecl = false;
public DocumentBuilderReceiver() {
super();
}
public DocumentBuilderReceiver(MemTreeBuilder builder) {
this(builder, false);
}
public DocumentBuilderReceiver(MemTreeBuilder builder, boolean declareNamespaces) {
super();
this.builder = builder;
this.explicitNSDecl = declareNamespaces;
}
public Document getDocument() {
return builder.getDocument();
}
public XQueryContext getContext() {
return builder.getContext();
}
/* (non-Javadoc)
* @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)
*/
public void setDocumentLocator(Locator arg0) {
}
/* (non-Javadoc)
* @see org.xml.sax.ContentHandler#startDocument()
*/
public void startDocument() throws SAXException {
if(builder == null) {
builder = new MemTreeBuilder();
builder.startDocument();
}
}
/* (non-Javadoc)
* @see org.xml.sax.ContentHandler#endDocument()
*/
public void endDocument() throws SAXException {
builder.endDocument();
}
/* (non-Javadoc)
* @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String)
*/
public void startPrefixMapping(String prefix, String namespace) throws SAXException {
if (!explicitNSDecl)
return;
if (namespaces == null)
namespaces = new HashMap();
namespaces.put(prefix, namespace);
}
/* (non-Javadoc)
* @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String)
*/
public void endPrefixMapping(String arg0) throws SAXException {
}
/* (non-Javadoc)
* @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
*/
public void startElement(String namespaceURI, String localName, String qName, Attributes attrs)
throws SAXException {
builder.startElement(namespaceURI, localName, qName, attrs);
declareNamespaces();
}
private void declareNamespaces() {
if (explicitNSDecl && namespaces != null) {
for (Iterator i = namespaces.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
builder.namespaceNode((String) entry.getKey(), (String) entry.getValue());
}
namespaces.clear();
}
}
public void startElement(QName qname, AttrList attribs) {
builder.startElement(qname, null);
declareNamespaces();
if(attribs != null) {
for (int i = 0; i < attribs.getLength(); i++) {
builder.addAttribute(attribs.getQName(i), attribs.getValue(i));
}
}
}
/* (non-Javadoc)
* @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
*/
public void endElement(String arg0, String arg1, String arg2) throws SAXException {
builder.endElement();
}
public void endElement(QName qname) throws SAXException {
builder.endElement();
}
public void addReferenceNode(NodeProxy proxy) throws SAXException {
builder.addReferenceNode(proxy);
}
public void addNamespaceNode(QName qname) throws SAXException {
builder.namespaceNode(qname);
}
public void characters(CharSequence seq) throws SAXException {
builder.characters(seq);
}
/* (non-Javadoc)
* @see org.xml.sax.ContentHandler#characters(char[], int, int)
*/
public void characters(char[] ch, int start, int len) throws SAXException {
builder.characters(ch, start, len);
}
public void attribute(QName qname, String value) throws SAXException {
try {
builder.addAttribute(qname, value);
} catch (DOMException e) {
throw new SAXException(e.getMessage());
}
}
/* (non-Javadoc)
* @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
*/
public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException {
}
/* (non-Javadoc)
* @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String)
*/
public void processingInstruction(String target, String data) throws SAXException {
builder.processingInstruction(target, data);
}
/* (non-Javadoc)
* @see org.exist.util.serializer.Receiver#cdataSection(char[], int, int)
*/
public void cdataSection(char[] ch, int start, int len) throws SAXException {
builder.cdataSection(new String(ch, start, len));
}
/* (non-Javadoc)
* @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String)
*/
public void skippedEntity(String arg0) throws SAXException {
}
/* (non-Javadoc)
* @see org.xml.sax.ext.LexicalHandler#endCDATA()
*/
public void endCDATA() throws SAXException {
// TODO ignored
}
/* (non-Javadoc)
* @see org.xml.sax.ext.LexicalHandler#endDTD()
*/
public void endDTD() throws SAXException {
}
/* (non-Javadoc)
* @see org.xml.sax.ext.LexicalHandler#startCDATA()
*/
public void startCDATA() throws SAXException {
// TODO Ignored
}
public void documentType(String name, String publicId, String systemId)throws SAXException {
builder.documentType(name, publicId, systemId);
}
/* (non-Javadoc)
* @see org.xml.sax.ext.LexicalHandler#comment(char[], int, int)
*/
public void comment(char[] ch, int start, int length) throws SAXException {
builder.comment(ch, start, length);
}
/* (non-Javadoc)
* @see org.xml.sax.ext.LexicalHandler#endEntity(java.lang.String)
*/
public void endEntity(String name) throws SAXException {
}
/* (non-Javadoc)
* @see org.xml.sax.ext.LexicalHandler#startEntity(java.lang.String)
*/
public void startEntity(String name) throws SAXException {
}
/* (non-Javadoc)
* @see org.xml.sax.ext.LexicalHandler#startDTD(java.lang.String, java.lang.String, java.lang.String)
*/
public void startDTD(String name, String publicId, String systemId) throws SAXException {
}
public void highlightText(CharSequence seq) {
// not supported with this receiver
}
public void setCurrentNode(StoredNode node) {
// ignored
}
}