package org.apache.xerces.parsers;

import java.io.IOException;
import java.util.Locale;
import org.apache.xerces.impl.xs.psvi.PSVIProvider;
import org.apache.xerces.util.EntityResolverWrapper;
import org.apache.xerces.util.ErrorHandlerWrapper;
import org.apache.xerces.util.SymbolHash;
import org.apache.xerces.xni.Augmentations;
import org.apache.xerces.xni.NamespaceContext;
import org.apache.xerces.xni.QName;
import org.apache.xerces.xni.XMLAttributes;
import org.apache.xerces.xni.XMLLocator;
import org.apache.xerces.xni.XMLResourceIdentifier;
import org.apache.xerces.xni.XMLString;
import org.apache.xerces.xni.XNIException;
import org.apache.xerces.xni.parser.XMLConfigurationException;
import org.apache.xerces.xni.parser.XMLEntityResolver;
import org.apache.xerces.xni.parser.XMLErrorHandler;
import org.apache.xerces.xni.parser.XMLInputSource;
import org.apache.xerces.xni.parser.XMLParseException;
import org.apache.xerces.xni.parser.XMLParserConfiguration;
import org.apache.xerces.xni.psvi.AttributePSVI;
import org.apache.xerces.xni.psvi.ElementPSVI;
import org.xml.sax.AttributeList;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.DocumentHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.Parser;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.DeclHandler;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.LocatorImpl;

public abstract class AbstractSAXParser extends AbstractXMLDocumentParser implements PSVIProvider, Parser, XMLReader {
  protected static final String NAMESPACES = "http://xml.org/sax/features/namespaces";
  
  protected static final String NAMESPACE_PREFIXES = "http://xml.org/sax/features/namespace-prefixes";
  
  protected static final String STRING_INTERNING = "http://xml.org/sax/features/string-interning";
  
  private static final String[] RECOGNIZED_FEATURES = new String[] { "http://xml.org/sax/features/namespaces", "http://xml.org/sax/features/namespace-prefixes", "http://xml.org/sax/features/string-interning" };
  
  protected static final String LEXICAL_HANDLER = "http://xml.org/sax/properties/lexical-handler";
  
  protected static final String DECLARATION_HANDLER = "http://xml.org/sax/properties/declaration-handler";
  
  protected static final String DOM_NODE = "http://xml.org/sax/properties/dom-node";
  
  private static final String[] RECOGNIZED_PROPERTIES = new String[] { "http://xml.org/sax/properties/lexical-handler", "http://xml.org/sax/properties/declaration-handler", "http://xml.org/sax/properties/dom-node" };
  
  protected boolean fNamespaces;
  
  protected boolean fNamespacePrefixes = false;
  
  protected ContentHandler fContentHandler;
  
  protected DocumentHandler fDocumentHandler;
  
  protected NamespaceContext fNamespaceContext;
  
  protected DTDHandler fDTDHandler;
  
  protected DeclHandler fDeclHandler;
  
  protected LexicalHandler fLexicalHandler;
  
  protected QName fQName = new QName();
  
  protected boolean fParseInProgress = false;
  
  private final AttributesProxy fAttributesProxy = new AttributesProxy();
  
  private Augmentations fAugmentations = null;
  
  private static final int BUFFER_SIZE = 20;
  
  private char[] fCharBuffer = new char[20];
  
  protected SymbolHash fDeclaredAttrs = null;
  
  protected AbstractSAXParser(XMLParserConfiguration config) {
    super(config);
    config.addRecognizedFeatures(RECOGNIZED_FEATURES);
    config.addRecognizedProperties(RECOGNIZED_PROPERTIES);
  }
  
  public void startDocument(XMLLocator locator, String encoding, NamespaceContext namespaceContext, Augmentations augs) throws XNIException {
    this.fNamespaceContext = namespaceContext;
    try {
      if (this.fDocumentHandler != null) {
        if (locator != null)
          this.fDocumentHandler.setDocumentLocator(new LocatorProxy(locator)); 
        this.fDocumentHandler.startDocument();
      } 
      if (this.fContentHandler != null) {
        if (locator != null)
          this.fContentHandler.setDocumentLocator(new LocatorProxy(locator)); 
        this.fContentHandler.startDocument();
      } 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void doctypeDecl(String rootElement, String publicId, String systemId, Augmentations augs) throws XNIException {
    this.fInDTD = true;
    try {
      if (this.fLexicalHandler != null)
        this.fLexicalHandler.startDTD(rootElement, publicId, systemId); 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
    if (this.fDeclHandler != null)
      this.fDeclaredAttrs = new SymbolHash(); 
  }
  
  public void startGeneralEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augs) throws XNIException {
    startParameterEntity(name, identifier, encoding, augs);
  }
  
  public void endGeneralEntity(String name, Augmentations augs) throws XNIException {
    endParameterEntity(name, augs);
  }
  
  public void startElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException {
    try {
      if (this.fDocumentHandler != null) {
        this.fAttributesProxy.setAttributes(attributes);
        this.fDocumentHandler.startElement(element.rawname, this.fAttributesProxy);
      } 
      if (this.fContentHandler != null) {
        startNamespaceMapping();
        this.fAugmentations = augs;
        int len = attributes.getLength();
        for (int i = len - 1; i >= 0; i--) {
          attributes.getName(i, this.fQName);
          if ((this.fQName.prefix != null && this.fQName.prefix.equals("xmlns")) || this.fQName.rawname.equals("xmlns")) {
            if (!this.fNamespacePrefixes)
              attributes.removeAttributeAt(i); 
            if (this.fNamespaces && this.fNamespacePrefixes) {
              this.fQName.prefix = "";
              this.fQName.uri = "";
              this.fQName.localpart = "";
              attributes.setName(i, this.fQName);
            } 
          } 
        } 
        String uri = (element.uri != null) ? element.uri : "";
        String localpart = this.fNamespaces ? element.localpart : "";
        this.fAttributesProxy.setAttributes(attributes);
        this.fContentHandler.startElement(uri, localpart, element.rawname, this.fAttributesProxy);
      } 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void characters(XMLString text, Augmentations augs) throws XNIException {
    if (text.length == 0)
      return; 
    try {
      if (this.fDocumentHandler != null)
        this.fDocumentHandler.characters(text.ch, text.offset, text.length); 
      if (this.fContentHandler != null)
        this.fContentHandler.characters(text.ch, text.offset, text.length); 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
    try {
      if (this.fDocumentHandler != null)
        this.fDocumentHandler.ignorableWhitespace(text.ch, text.offset, text.length); 
      if (this.fContentHandler != null)
        this.fContentHandler.ignorableWhitespace(text.ch, text.offset, text.length); 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void endElement(QName element, Augmentations augs) throws XNIException {
    try {
      if (this.fDocumentHandler != null)
        this.fDocumentHandler.endElement(element.rawname); 
      if (this.fContentHandler != null) {
        this.fAugmentations = augs;
        String uri = (element.uri != null) ? element.uri : "";
        String localpart = this.fNamespaces ? element.localpart : "";
        this.fContentHandler.endElement(uri, localpart, element.rawname);
        endNamespaceMapping();
      } 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void startCDATA(Augmentations augs) throws XNIException {
    try {
      if (this.fLexicalHandler != null)
        this.fLexicalHandler.startCDATA(); 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void endCDATA(Augmentations augs) throws XNIException {
    try {
      if (this.fLexicalHandler != null)
        this.fLexicalHandler.endCDATA(); 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void comment(XMLString text, Augmentations augs) throws XNIException {
    try {
      if (this.fLexicalHandler != null)
        this.fLexicalHandler.comment(text.ch, 0, text.length); 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void processingInstruction(String target, XMLString data, Augmentations augs) throws XNIException {
    try {
      if (this.fDocumentHandler != null)
        this.fDocumentHandler.processingInstruction(target, data.toString()); 
      if (this.fContentHandler != null)
        this.fContentHandler.processingInstruction(target, data.toString()); 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void endDocument(Augmentations augs) throws XNIException {
    try {
      if (this.fDocumentHandler != null)
        this.fDocumentHandler.endDocument(); 
      if (this.fContentHandler != null)
        this.fContentHandler.endDocument(); 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void startExternalSubset(XMLResourceIdentifier identifier, Augmentations augs) throws XNIException {
    startParameterEntity("[dtd]", (XMLResourceIdentifier)null, (String)null, augs);
  }
  
  public void endExternalSubset(Augmentations augs) throws XNIException {
    endParameterEntity("[dtd]", augs);
  }
  
  public void startParameterEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augs) throws XNIException {
    try {
      if (this.fLexicalHandler != null)
        this.fLexicalHandler.startEntity(name); 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void endParameterEntity(String name, Augmentations augs) throws XNIException {
    try {
      if (this.fLexicalHandler != null)
        this.fLexicalHandler.endEntity(name); 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void elementDecl(String name, String contentModel, Augmentations augs) throws XNIException {
    try {
      if (this.fDeclHandler != null)
        this.fDeclHandler.elementDecl(name, contentModel); 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void attributeDecl(String elementName, String attributeName, String type, String[] enumeration, String defaultType, XMLString defaultValue, XMLString nonNormalizedDefaultValue, Augmentations augs) throws XNIException {
    try {
      if (this.fDeclHandler != null) {
        String elemAttr = elementName + "<" + attributeName;
        if (this.fDeclaredAttrs.get(elemAttr) != null)
          return; 
        this.fDeclaredAttrs.put(elemAttr, Boolean.TRUE);
        if (type.equals("NOTATION") || type.equals("ENUMERATION")) {
          StringBuffer str = new StringBuffer();
          if (type.equals("NOTATION")) {
            str.append(type);
            str.append(" (");
          } else {
            str.append("(");
          } 
          for (int i = 0; i < enumeration.length; i++) {
            str.append(enumeration[i]);
            if (i < enumeration.length - 1)
              str.append('|'); 
          } 
          str.append(')');
          type = str.toString();
        } 
        String value = (defaultValue == null) ? null : defaultValue.toString();
        this.fDeclHandler.attributeDecl(elementName, attributeName, type, defaultType, value);
      } 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void internalEntityDecl(String name, XMLString text, XMLString nonNormalizedText, Augmentations augs) throws XNIException {
    try {
      if (this.fDeclHandler != null)
        this.fDeclHandler.internalEntityDecl(name, text.toString()); 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void externalEntityDecl(String name, XMLResourceIdentifier identifier, Augmentations augs) throws XNIException {
    String publicId = identifier.getPublicId();
    String literalSystemId = identifier.getLiteralSystemId();
    try {
      if (this.fDeclHandler != null)
        this.fDeclHandler.externalEntityDecl(name, publicId, literalSystemId); 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void unparsedEntityDecl(String name, XMLResourceIdentifier identifier, String notation, Augmentations augs) throws XNIException {
    String publicId = identifier.getPublicId();
    String expandedSystemId = identifier.getExpandedSystemId();
    try {
      if (this.fDTDHandler != null)
        this.fDTDHandler.unparsedEntityDecl(name, publicId, expandedSystemId, notation); 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void notationDecl(String name, XMLResourceIdentifier identifier, Augmentations augs) throws XNIException {
    String publicId = identifier.getPublicId();
    String expandedSystemId = identifier.getExpandedSystemId();
    try {
      if (this.fDTDHandler != null)
        this.fDTDHandler.notationDecl(name, publicId, expandedSystemId); 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
  }
  
  public void endDTD(Augmentations augs) throws XNIException {
    this.fInDTD = false;
    try {
      if (this.fLexicalHandler != null)
        this.fLexicalHandler.endDTD(); 
    } catch (SAXException e) {
      throw new XNIException(e);
    } 
    if (this.fDeclaredAttrs != null)
      this.fDeclaredAttrs.clear(); 
  }
  
  public void parse(String systemId) throws SAXException, IOException {
    XMLInputSource source = new XMLInputSource(null, systemId, null);
    try {
      parse(source);
    } catch (XMLParseException e) {
      Exception ex = e.getException();
      if (ex == null) {
        LocatorImpl locatorImpl = new LocatorImpl();
        locatorImpl.setPublicId(e.getPublicId());
        locatorImpl.setSystemId(e.getExpandedSystemId());
        locatorImpl.setLineNumber(e.getLineNumber());
        locatorImpl.setColumnNumber(e.getColumnNumber());
        throw new SAXParseException(e.getMessage(), locatorImpl);
      } 
      if (ex instanceof SAXException)
        throw (SAXException)ex; 
      if (ex instanceof IOException)
        throw (IOException)ex; 
      throw new SAXException(ex);
    } catch (XNIException e) {
      Exception ex = e.getException();
      if (ex == null)
        throw new SAXException(e.getMessage()); 
      if (ex instanceof SAXException)
        throw (SAXException)ex; 
      if (ex instanceof IOException)
        throw (IOException)ex; 
      throw new SAXException(ex);
    } 
  }
  
  public void parse(InputSource inputSource) throws SAXException, IOException {
    try {
      XMLInputSource xmlInputSource = new XMLInputSource(inputSource.getPublicId(), inputSource.getSystemId(), null);
      xmlInputSource.setByteStream(inputSource.getByteStream());
      xmlInputSource.setCharacterStream(inputSource.getCharacterStream());
      xmlInputSource.setEncoding(inputSource.getEncoding());
      parse(xmlInputSource);
    } catch (XMLParseException e) {
      Exception ex = e.getException();
      if (ex == null) {
        LocatorImpl locatorImpl = new LocatorImpl();
        locatorImpl.setPublicId(e.getPublicId());
        locatorImpl.setSystemId(e.getExpandedSystemId());
        locatorImpl.setLineNumber(e.getLineNumber());
        locatorImpl.setColumnNumber(e.getColumnNumber());
        throw new SAXParseException(e.getMessage(), locatorImpl);
      } 
      if (ex instanceof SAXException)
        throw (SAXException)ex; 
      if (ex instanceof IOException)
        throw (IOException)ex; 
      throw new SAXException(ex);
    } catch (XNIException e) {
      Exception ex = e.getException();
      if (ex == null)
        throw new SAXException(e.getMessage()); 
      if (ex instanceof SAXException)
        throw (SAXException)ex; 
      if (ex instanceof IOException)
        throw (IOException)ex; 
      throw new SAXException(ex);
    } 
  }
  
  public void setEntityResolver(EntityResolver resolver) {
    if (resolver == null)
      throw new NullPointerException(); 
    try {
      this.fConfiguration.setProperty("http://apache.org/xml/properties/internal/entity-resolver", new EntityResolverWrapper(resolver));
    } catch (XMLConfigurationException e) {}
  }
  
  public EntityResolver getEntityResolver() {
    EntityResolver entityResolver = null;
    try {
      XMLEntityResolver xmlEntityResolver = (XMLEntityResolver)this.fConfiguration.getProperty("http://apache.org/xml/properties/internal/entity-resolver");
      if (xmlEntityResolver != null && xmlEntityResolver instanceof EntityResolverWrapper)
        entityResolver = ((EntityResolverWrapper)xmlEntityResolver).getEntityResolver(); 
    } catch (XMLConfigurationException e) {}
    return entityResolver;
  }
  
  public void setErrorHandler(ErrorHandler errorHandler) {
    if (errorHandler == null)
      throw new NullPointerException(); 
    try {
      this.fConfiguration.setProperty("http://apache.org/xml/properties/internal/error-handler", new ErrorHandlerWrapper(errorHandler));
    } catch (XMLConfigurationException e) {}
  }
  
  public ErrorHandler getErrorHandler() {
    ErrorHandler errorHandler = null;
    try {
      XMLErrorHandler xmlErrorHandler = (XMLErrorHandler)this.fConfiguration.getProperty("http://apache.org/xml/properties/internal/error-handler");
      if (xmlErrorHandler != null && xmlErrorHandler instanceof ErrorHandlerWrapper)
        errorHandler = ((ErrorHandlerWrapper)xmlErrorHandler).getErrorHandler(); 
    } catch (XMLConfigurationException e) {}
    return errorHandler;
  }
  
  public void setLocale(Locale locale) throws SAXException {
    this.fConfiguration.setLocale(locale);
  }
  
  public void setDTDHandler(DTDHandler dtdHandler) {
    if (dtdHandler == null)
      throw new NullPointerException(); 
    this.fDTDHandler = dtdHandler;
  }
  
  public void setDocumentHandler(DocumentHandler documentHandler) {
    this.fDocumentHandler = documentHandler;
  }
  
  public void setContentHandler(ContentHandler contentHandler) {
    if (contentHandler == null)
      throw new NullPointerException(); 
    this.fContentHandler = contentHandler;
  }
  
  public ContentHandler getContentHandler() {
    return this.fContentHandler;
  }
  
  public DTDHandler getDTDHandler() {
    return this.fDTDHandler;
  }
  
  public void setFeature(String featureId, boolean state) throws SAXNotRecognizedException, SAXNotSupportedException {
    try {
      if (featureId.startsWith("http://xml.org/sax/features/")) {
        String feature = featureId.substring("http://xml.org/sax/features/".length());
        if (feature.equals("namespaces")) {
          this.fConfiguration.setFeature(featureId, state);
          this.fNamespaces = state;
          return;
        } 
        if (feature.equals("namespace-prefixes")) {
          this.fConfiguration.setFeature(featureId, state);
          this.fNamespacePrefixes = state;
          return;
        } 
        if (feature.equals("string-interning")) {
          if (!state)
            throw new SAXNotSupportedException("PAR018 " + state + " state for feature \"" + featureId + "\" is not supported.\n" + state + '\t' + featureId); 
          return;
        } 
      } 
      this.fConfiguration.setFeature(featureId, state);
    } catch (XMLConfigurationException e) {
      String message = e.getMessage();
      if (e.getType() == 0)
        throw new SAXNotRecognizedException(message); 
      throw new SAXNotSupportedException(message);
    } 
  }
  
  public boolean getFeature(String featureId) throws SAXNotRecognizedException, SAXNotSupportedException {
    try {
      if (featureId.startsWith("http://xml.org/sax/features/")) {
        String feature = featureId.substring("http://xml.org/sax/features/".length());
        if (feature.equals("namespace-prefixes")) {
          boolean state = this.fConfiguration.getFeature(featureId);
          return state;
        } 
        if (feature.equals("string-interning"))
          return true; 
      } 
      return this.fConfiguration.getFeature(featureId);
    } catch (XMLConfigurationException e) {
      String message = e.getMessage();
      if (e.getType() == 0)
        throw new SAXNotRecognizedException(message); 
      throw new SAXNotSupportedException(message);
    } 
  }
  
  public void setProperty(String propertyId, Object value) throws SAXNotRecognizedException, SAXNotSupportedException {
    try {
      if (propertyId.startsWith("http://xml.org/sax/properties/")) {
        String property = propertyId.substring("http://xml.org/sax/properties/".length());
        if (property.equals("lexical-handler")) {
          try {
            setLexicalHandler((LexicalHandler)value);
          } catch (ClassCastException e) {
            throw new SAXNotSupportedException("PAR012 For propertyID \"" + propertyId + "\", the value \"" + value + "\" cannot be cast to LexicalHandler." + '\n' + propertyId + '\t' + value + "\tLexicalHandler");
          } 
          return;
        } 
        if (property.equals("declaration-handler")) {
          try {
            setDeclHandler((DeclHandler)value);
          } catch (ClassCastException e) {
            throw new SAXNotSupportedException("PAR012 For propertyID \"" + propertyId + "\", the value \"" + value + "\" cannot be cast to DeclHandler." + '\n' + propertyId + '\t' + value + "\tDeclHandler");
          } 
          return;
        } 
        if (property.equals("dom-node"))
          throw new SAXNotSupportedException("PAR013 Property \"" + propertyId + "\" is read only." + '\n' + propertyId); 
      } 
      this.fConfiguration.setProperty(propertyId, value);
    } catch (XMLConfigurationException e) {
      String message = e.getMessage();
      if (e.getType() == 0)
        throw new SAXNotRecognizedException(message); 
      throw new SAXNotSupportedException(message);
    } 
  }
  
  public Object getProperty(String propertyId) throws SAXNotRecognizedException, SAXNotSupportedException {
    try {
      if (propertyId.startsWith("http://xml.org/sax/properties/")) {
        String property = propertyId.substring("http://xml.org/sax/properties/".length());
        if (property.equals("lexical-handler"))
          return getLexicalHandler(); 
        if (property.equals("declaration-handler"))
          return getDeclHandler(); 
        if (property.equals("dom-node"))
          throw new SAXNotSupportedException("PAR014 Cannot getProperty(\"" + propertyId + "\". No DOM Tree exists.\n" + propertyId); 
      } 
      return this.fConfiguration.getProperty(propertyId);
    } catch (XMLConfigurationException e) {
      String message = e.getMessage();
      if (e.getType() == 0)
        throw new SAXNotRecognizedException(message); 
      throw new SAXNotSupportedException(message);
    } 
  }
  
  protected void setDeclHandler(DeclHandler handler) throws SAXNotRecognizedException, SAXNotSupportedException {
    if (this.fParseInProgress)
      throw new SAXNotSupportedException("PAR011 Feature: http://xml.org/sax/properties/declaration-handler is not supported during parse.\nhttp://xml.org/sax/properties/declaration-handler"); 
    this.fDeclHandler = handler;
  }
  
  protected DeclHandler getDeclHandler() throws SAXNotRecognizedException, SAXNotSupportedException {
    return this.fDeclHandler;
  }
  
  protected void setLexicalHandler(LexicalHandler handler) throws SAXNotRecognizedException, SAXNotSupportedException {
    if (this.fParseInProgress)
      throw new SAXNotSupportedException("PAR011 Feature: http://xml.org/sax/properties/lexical-handler is not supported during parse.\nhttp://xml.org/sax/properties/lexical-handler"); 
    this.fLexicalHandler = handler;
  }
  
  protected LexicalHandler getLexicalHandler() throws SAXNotRecognizedException, SAXNotSupportedException {
    return this.fLexicalHandler;
  }
  
  protected final void startNamespaceMapping() throws SAXException {
    int count = this.fNamespaceContext.getDeclaredPrefixCount();
    if (count > 0) {
      String prefix = null;
      String uri = null;
      for (int i = 0; i < count; i++) {
        prefix = this.fNamespaceContext.getDeclaredPrefixAt(i);
        uri = this.fNamespaceContext.getURI(prefix);
        this.fContentHandler.startPrefixMapping(prefix, (uri == null) ? "" : uri);
      } 
    } 
  }
  
  protected final void endNamespaceMapping() throws SAXException {
    int count = this.fNamespaceContext.getDeclaredPrefixCount();
    if (count > 0)
      for (int i = 0; i < count; i++)
        this.fContentHandler.endPrefixMapping(this.fNamespaceContext.getDeclaredPrefixAt(i));  
  }
  
  public void reset() throws XNIException {
    super.reset();
    this.fInDTD = false;
    this.fNamespaces = this.fConfiguration.getFeature("http://xml.org/sax/features/namespaces");
    this.fNamespacePrefixes = this.fConfiguration.getFeature("http://xml.org/sax/features/namespace-prefixes");
    this.fAugmentations = null;
    this.fDeclaredAttrs = null;
  }
  
  protected static class LocatorProxy implements Locator {
    protected XMLLocator fLocator;
    
    public LocatorProxy(XMLLocator locator) {
      this.fLocator = locator;
    }
    
    public String getPublicId() {
      return this.fLocator.getPublicId();
    }
    
    public String getSystemId() {
      return this.fLocator.getExpandedSystemId();
    }
    
    public int getLineNumber() {
      return this.fLocator.getLineNumber();
    }
    
    public int getColumnNumber() {
      return this.fLocator.getColumnNumber();
    }
  }
  
  protected static final class AttributesProxy implements AttributeList, Attributes {
    protected XMLAttributes fAttributes;
    
    public void setAttributes(XMLAttributes attributes) {
      this.fAttributes = attributes;
    }
    
    public int getLength() {
      return this.fAttributes.getLength();
    }
    
    public String getName(int i) {
      return this.fAttributes.getQName(i);
    }
    
    public String getQName(int index) {
      return this.fAttributes.getQName(index);
    }
    
    public String getURI(int index) {
      String uri = this.fAttributes.getURI(index);
      return (uri != null) ? uri : "";
    }
    
    public String getLocalName(int index) {
      return this.fAttributes.getLocalName(index);
    }
    
    public String getType(int i) {
      return this.fAttributes.getType(i);
    }
    
    public String getType(String name) {
      return this.fAttributes.getType(name);
    }
    
    public String getType(String uri, String localName) {
      return uri.equals("") ? this.fAttributes.getType(null, localName) : this.fAttributes.getType(uri, localName);
    }
    
    public String getValue(int i) {
      return this.fAttributes.getValue(i);
    }
    
    public String getValue(String name) {
      return this.fAttributes.getValue(name);
    }
    
    public String getValue(String uri, String localName) {
      return uri.equals("") ? this.fAttributes.getValue(null, localName) : this.fAttributes.getValue(uri, localName);
    }
    
    public int getIndex(String qName) {
      return this.fAttributes.getIndex(qName);
    }
    
    public int getIndex(String uri, String localPart) {
      return uri.equals("") ? this.fAttributes.getIndex(null, localPart) : this.fAttributes.getIndex(uri, localPart);
    }
  }
  
  public ElementPSVI getElementPSVI() {
    return (this.fAugmentations != null) ? (ElementPSVI)this.fAugmentations.getItem("ELEMENT_PSVI") : null;
  }
  
  public AttributePSVI getAttributePSVI(int index) {
    return (AttributePSVI)this.fAttributesProxy.fAttributes.getAugmentations(index).getItem("ATTRIBUTE_PSVI");
  }
  
  public AttributePSVI getAttributePSVIByName(String uri, String localname) {
    return (AttributePSVI)this.fAttributesProxy.fAttributes.getAugmentations(uri, localname).getItem("ATTRIBUTE_PSVI");
  }
}
