package com.dbxml.xml.sax;
/*
* dbXML - Native XML Database
* Copyright (c) 1999-2006 The dbXML Group, L.L.C.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* $Id: SAXProducer.java,v 1.8 2006/02/02 19:04:46 bradford Exp $
*/
import java.util.*;
import org.xml.sax.*;
import com.dbxml.util.UTF8;
import com.dbxml.xml.QName;
import com.dbxml.xml.dtsm.Constants;
import com.dbxml.xml.dtsm.Consumer;
import com.dbxml.xml.dtsm.DocumentTable;
import com.dbxml.xml.dtsm.DocumentTableEntry;
import com.dbxml.xml.dtsm.Producer;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.AttributesImpl;
/**
* SAXProducer
*/
public final class SAXProducer extends Producer implements Consumer {
private static final AttributesImpl EmptyAttributes = new AttributesImpl();
private Set features = new HashSet();
private ContentHandler content;
private ErrorHandler errors;
private EntityResolver entities;
private DTDHandler dtd;
private LexicalHandler lex;
private boolean nsReporting;
private boolean nsPrefixes;
private Stack prefixStack; // of Map
private AttributesImpl attrs;
public SAXProducer(DocumentTable table) {
setDocumentTable(table);
}
public SAXProducer(DocumentTable table, ContentHandler handler) {
setDocumentTable(table);
setContentHandler(handler);
}
public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
return features.contains(name);
}
public void setFeature(String name, boolean value) throws SAXNotRecognizedException, SAXNotSupportedException {
if ( value ) {
if ( !features.contains(name) )
features.add(name);
}
else {
if ( features.contains(name) )
features.remove(name);
}
}
public void setProperty(String name, Object value) {
super.setProperty(name, value);
if ( name.equals("http://xml.org/sax/properties/lexical-handler") ) {
if ( value instanceof LexicalHandler )
lex = (LexicalHandler)value;
else
lex = null;
}
}
public void setEntityResolver(EntityResolver resolver) {
entities = resolver;
}
public EntityResolver getEntityResolver() {
return entities;
}
public void setDTDHandler(DTDHandler handler) {
dtd = handler;
}
public DTDHandler getDTDHandler() {
return dtd;
}
public void setContentHandler(ContentHandler handler) {
content = handler;
}
public ContentHandler getContentHandler() {
return content;
}
public void setErrorHandler(ErrorHandler handler) {
errors = handler;
}
public ErrorHandler getErrorHandler() {
return errors;
}
public void process(Consumer consumer) throws Exception {
nsReporting = features.contains("http://xml.org/sax/features/namespaces");
nsPrefixes = features.contains("http://xml.org/sax/features/namespace-prefixes");
if ( nsReporting )
prefixStack = new Stack();
super.process(consumer);
}
public void beginDocument(DocumentTableEntry entry) {
}
public void endDocument(DocumentTableEntry entry) {
}
public void beginElement(DocumentTableEntry entry) throws Exception {
if ( nsReporting )
prefixStack.push(new HashMap());
int symID = entry.getValID();
QName qname = symbols.getQName(symID);
String uri = qname.getSAXURI();
if ( processor.peek().getTypeID() == Constants.OBJ_BEGIN_ATTRIBUTE )
attrs = new AttributesImpl();
else
attrs = EmptyAttributes;
while ( processor.peek().getTypeID() == Constants.OBJ_BEGIN_ATTRIBUTE )
attribute(processor.next());
content.startElement(uri, qname.getLocalName(), qname.getName(), attrs);
}
public void endElement(DocumentTableEntry entry) throws Exception {
int symID = entry.getValID();
QName qname = symbols.getQName(symID);
String uri = qname.getSAXURI();
content.endElement(uri, qname.getLocalName(), qname.getName());
if ( nsReporting ) {
Map prefixMap = (Map)prefixStack.pop();
if ( prefixMap.size() > 0 ) {
Iterator keys = prefixMap.keySet().iterator();
while ( keys.hasNext() )
content.endPrefixMapping((String)keys.next());
}
}
}
public void attribute(DocumentTableEntry entry) throws Exception {
int symID = entry.getValID();
QName qname = symbols.getQName(symID);
String uri = qname.getSAXURI();
StringBuffer sb = new StringBuffer();
do {
entry = processor.next();
if ( entry.getTypeID() == Constants.OBJ_TEXT ) {
int valID = entry.getValID();
sb.append(UTF8.toCharArray(table.getValue(valID)));
}
}
while ( entry.getTypeID() != Constants.OBJ_END_ATTRIBUTE );
String value = sb.toString();
if ( nsReporting && qname.isNamespaceDecl() ) {
Map prefixMap = (Map)prefixStack.peek();
String prefix = qname.getSAXPrefix();
prefixMap.put(prefix, value);
content.startPrefixMapping(prefix, value);
if ( nsPrefixes )
attrs.addAttribute(uri, qname.getLocalName(), qname.getName(), "", value);
}
else
attrs.addAttribute(uri, qname.getLocalName(), qname.getName(), "", value);
}
public void procInst(DocumentTableEntry entry) throws Exception {
int symID = entry.getValID();
QName qname = symbols.getQName(symID);
entry = processor.next();
int valID = entry.getValID();
String data = table.getValue(valID).toString();
processor.next(); // Eat the OBJ_END_PROCINST
content.processingInstruction(qname.getName(), data);
}
public void text(DocumentTableEntry entry) throws Exception {
int valID = entry.getValID();
char[] data = UTF8.toCharArray(table.getValue(valID));
content.characters(data, 0, data.length);
}
public void cdata(DocumentTableEntry entry) throws Exception {
int valID = entry.getValID();
char[] data = UTF8.toCharArray(table.getValue(valID));
if ( lex != null ) {
lex.startCDATA();
content.characters(data, 0, data.length);
lex.endCDATA();
}
else
content.characters(data, 0, data.length);
}
public void comment(DocumentTableEntry entry) throws Exception {
int valID = entry.getValID();
char[] data = UTF8.toCharArray(table.getValue(valID));
if ( lex != null )
lex.comment(data, 0, data.length);
}
public void entity(DocumentTableEntry entry) throws Exception {
int symID = entry.getValID();
String name = symbols.getQName(symID).getName();
entry = processor.next(); // Get Public ID
int pubID = entry.getValID();
entry = processor.next(); // Get System ID
int sysID = entry.getValID();
entry = processor.next(); // Get Notation Name
int notID = entry.getValID();
processor.next(); // Eat the OBJ_END_ENTITY
if ( dtd != null ) {
String publicID = table.getValue(pubID).toString();
String systemID = table.getValue(sysID).toString();
String notation = table.getValue(notID).toString();
dtd.unparsedEntityDecl(name, publicID, systemID, notation);
}
}
public void notation(DocumentTableEntry entry) throws Exception {
int symID = entry.getValID();
String name = symbols.getQName(symID).getName();
entry = processor.next(); // Get Public ID
int pubID = entry.getValID();
entry = processor.next(); // Get System ID
int sysID = entry.getValID();
processor.next(); // Eat the OBJ_END_NOTATION
if ( dtd != null ) {
String publicID = table.getValue(pubID).toString();
String systemID = table.getValue(sysID).toString();
dtd.notationDecl(name, publicID, systemID);
}
}
public void docType(DocumentTableEntry entry) throws Exception {
processor.next(); // Eat the OBJ_END_DOCTYPE
}
public void entityRef(DocumentTableEntry entry) throws Exception {
/** @todo This */
}
}