FileDocCategorySizeDatePackage
DOMValidatorHelper.javaAPI DocApache Xerces 3.0.124713Fri Sep 14 20:33:52 BST 2007org.apache.xerces.jaxp.validation

DOMValidatorHelper

public final class DOMValidatorHelper extends Object implements ValidatorHelper, org.apache.xerces.impl.validation.EntityState

A validator helper for DOMSources.

author
Michael Glavassevich, IBM
version
$Id: DOMValidatorHelper.java 542517 2007-05-29 13:47:06Z mrglavas $

Fields Summary
private static final int
CHUNK_SIZE
Chunk size (1024).
private static final int
CHUNK_MASK
Chunk mask (CHUNK_SIZE - 1).
private static final String
ERROR_REPORTER
Property identifier: error reporter.
private static final String
NAMESPACE_CONTEXT
Property identifier: namespace context.
private static final String
SCHEMA_VALIDATOR
Property identifier: XML Schema validator.
private static final String
SYMBOL_TABLE
Property identifier: symbol table.
private static final String
VALIDATION_MANAGER
Property identifier: validation manager.
private final org.apache.xerces.impl.XMLErrorReporter
fErrorReporter
Error reporter.
private final org.apache.xerces.util.NamespaceSupport
fNamespaceContext
The namespace context of this document: stores namespaces in scope.
private final DOMNamespaceContext
fDOMNamespaceContext
The namespace context of the DOMSource, includes context from ancestor nodes.
private final org.apache.xerces.impl.xs.XMLSchemaValidator
fSchemaValidator
Schema validator.
private final org.apache.xerces.util.SymbolTable
fSymbolTable
Symbol table
private final org.apache.xerces.impl.validation.ValidationManager
fValidationManager
Validation manager.
private final XMLSchemaValidatorComponentManager
fComponentManager
Component manager.
private final org.apache.xerces.impl.xs.util.SimpleLocator
fXMLLocator
Simple Locator.
private DOMDocumentHandler
fDOMValidatorHandler
DOM document handler.
private final DOMResultAugmentor
fDOMResultAugmentor
DOM result augmentor.
private final DOMResultBuilder
fDOMResultBuilder
DOM result builder.
private NamedNodeMap
fEntities
Map for tracking unparsed entities.
private final char[]
fCharBuffer
Array for holding character data.
private Node
fRoot
Root node.
private Node
fCurrentElement
Current element.
final org.apache.xerces.xni.QName
fElementQName
Fields for start element, end element and characters.
final org.apache.xerces.xni.QName
fAttributeQName
final org.apache.xerces.util.XMLAttributesImpl
fAttributes
final org.apache.xerces.xni.XMLString
fTempString
Constructors Summary
public DOMValidatorHelper(XMLSchemaValidatorComponentManager componentManager)

    
       
        fComponentManager = componentManager;
        fErrorReporter = (XMLErrorReporter) fComponentManager.getProperty(ERROR_REPORTER);
        fNamespaceContext = (NamespaceSupport) fComponentManager.getProperty(NAMESPACE_CONTEXT);
        fSchemaValidator = (XMLSchemaValidator) fComponentManager.getProperty(SCHEMA_VALIDATOR);
        fSymbolTable = (SymbolTable) fComponentManager.getProperty(SYMBOL_TABLE);        
        fValidationManager = (ValidationManager) fComponentManager.getProperty(VALIDATION_MANAGER);
    
Methods Summary
private voidbeginNode(org.w3c.dom.Node node)
Do processing for the start of a node.

        switch (node.getNodeType()) {
            case Node.ELEMENT_NODE:
                fCurrentElement = node;
                // push namespace context
                fNamespaceContext.pushContext();
                // start element
                fillQName(fElementQName, node);
                processAttributes(node.getAttributes());
                fSchemaValidator.startElement(fElementQName, fAttributes, null);
                break;
            case Node.TEXT_NODE:
                if (fDOMValidatorHandler != null) {
                    fDOMValidatorHandler.setIgnoringCharacters(true);
                    sendCharactersToValidator(node.getNodeValue());
                    fDOMValidatorHandler.setIgnoringCharacters(false);
                    fDOMValidatorHandler.characters((Text) node);
                }
                else {
                    sendCharactersToValidator(node.getNodeValue());
                }
                break;
            case Node.CDATA_SECTION_NODE:
                if (fDOMValidatorHandler != null) {
                    fDOMValidatorHandler.setIgnoringCharacters(true);
                    fSchemaValidator.startCDATA(null);
                    sendCharactersToValidator(node.getNodeValue());
                    fSchemaValidator.endCDATA(null);
                    fDOMValidatorHandler.setIgnoringCharacters(false);
                    fDOMValidatorHandler.cdata((CDATASection) node);
                }
                else {
                    fSchemaValidator.startCDATA(null);
                    sendCharactersToValidator(node.getNodeValue());
                    fSchemaValidator.endCDATA(null); 
                }
                break;
            case Node.PROCESSING_INSTRUCTION_NODE:
                /** 
                 * The validator does nothing with processing instructions so bypass it.
                 * Send the ProcessingInstruction node directly to the result builder.
                 */
                if (fDOMValidatorHandler != null) {
                    fDOMValidatorHandler.processingInstruction((ProcessingInstruction) node);
                }
                break;
            case Node.COMMENT_NODE:
                /** 
                 * The validator does nothing with comments so bypass it.
                 * Send the Comment node directly to the result builder.
                 */
                if (fDOMValidatorHandler != null) {
                    fDOMValidatorHandler.comment((Comment) node);
                }
                break;
            case Node.DOCUMENT_TYPE_NODE:
                /** 
                 * Send the DocumentType node directly to the result builder.
                 */
                if (fDOMValidatorHandler != null) {
                    fDOMValidatorHandler.doctypeDecl((DocumentType) node);
                }
                break;
            default: // Ignore other node types.
                break;
        }
    
private voidfillQName(org.apache.xerces.xni.QName toFill, org.w3c.dom.Node node)

        final String prefix = node.getPrefix();
        final String localName = node.getLocalName();
        final String rawName = node.getNodeName();
        final String namespace = node.getNamespaceURI();
        toFill.prefix = (prefix != null) ? fSymbolTable.addSymbol(prefix) : XMLSymbols.EMPTY_STRING;
        toFill.localpart = (localName != null) ? fSymbolTable.addSymbol(localName) : XMLSymbols.EMPTY_STRING;
        toFill.rawname = (rawName != null) ? fSymbolTable.addSymbol(rawName) : XMLSymbols.EMPTY_STRING; 
        toFill.uri = (namespace != null && namespace.length() > 0) ? fSymbolTable.addSymbol(namespace) : null;
    
private voidfinishNode(org.w3c.dom.Node node)
Do processing for the end of a node.

        if (node.getNodeType() == Node.ELEMENT_NODE) {
            fCurrentElement = node;
            // end element
            fillQName(fElementQName, node);
            fSchemaValidator.endElement(fElementQName, null);
            // pop namespace context
            fNamespaceContext.popContext();
        }
    
org.w3c.dom.NodegetCurrentElement()
Returns the current element node.

        return fCurrentElement;
    
public booleanisEntityDeclared(java.lang.String name)

        return false;
    
public booleanisEntityUnparsed(java.lang.String name)

        if (fEntities != null) {
            Entity entity = (Entity) fEntities.getNamedItem(name);
            if (entity != null) {
                return (entity.getNotationName() != null);
            }
        }
        return false;
    
private voidprocessAttributes(org.w3c.dom.NamedNodeMap attrMap)

        final int attrCount = attrMap.getLength();
        fAttributes.removeAllAttributes();
        for (int i = 0; i < attrCount; ++i) {
            Attr attr = (Attr) attrMap.item(i);
            String value = attr.getValue();
            if (value == null) {
                value = XMLSymbols.EMPTY_STRING;
            }
            fillQName(fAttributeQName, attr);
            // REVISIT: Assuming all attributes are of type CDATA. The actual type may not matter. -- mrglavas
            fAttributes.addAttributeNS(fAttributeQName, XMLSymbols.fCDATASymbol, value);
            fAttributes.setSpecified(i, attr.getSpecified());
            // REVISIT: Should we be looking at non-namespace attributes
            // for additional mappings? Should we detect illegal namespace
            // declarations and exclude them from the context? -- mrglavas
            if (fAttributeQName.uri == NamespaceContext.XMLNS_URI) {
                // process namespace attribute
                if (fAttributeQName.prefix == XMLSymbols.PREFIX_XMLNS) {
                    fNamespaceContext.declarePrefix(fAttributeQName.localpart, value.length() != 0 ? fSymbolTable.addSymbol(value) : null);
                }
                else {
                    fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, value.length() != 0 ? fSymbolTable.addSymbol(value) : null);
                }
            }
        }
    
private voidsendCharactersToValidator(java.lang.String str)

        if (str != null) {
            final int length = str.length();
            final int remainder = length & CHUNK_MASK;
            if (remainder > 0) {
                str.getChars(0, remainder, fCharBuffer, 0);
                fTempString.setValues(fCharBuffer, 0, remainder);
                fSchemaValidator.characters(fTempString, null);
            }
            int i = remainder;
            while (i < length) {
                str.getChars(i, i += CHUNK_SIZE, fCharBuffer, 0);
                fTempString.setValues(fCharBuffer, 0, CHUNK_SIZE);
                fSchemaValidator.characters(fTempString, null);
            }
        }
    
private voidsetupDOMResultHandler(javax.xml.transform.dom.DOMSource source, javax.xml.transform.dom.DOMResult result)
Sets up handler for DOMResult.

        // If there's no DOMResult, unset the validator handler
        if (result == null) {
            fDOMValidatorHandler = null;
            fSchemaValidator.setDocumentHandler(null);
            return;
        }
        final Node nodeResult = result.getNode();
        // If the source node and result node are the same use the DOMResultAugmentor.
        // Otherwise use the DOMResultBuilder.
        if (source.getNode() == nodeResult) {
            fDOMValidatorHandler = fDOMResultAugmentor;
            fDOMResultAugmentor.setDOMResult(result);
            fSchemaValidator.setDocumentHandler(fDOMResultAugmentor);
            return;
        }
        if (result.getNode() == null) {
            try {
                DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
                factory.setNamespaceAware(true);
                DocumentBuilder builder = factory.newDocumentBuilder();
                result.setNode(builder.newDocument());
            }
            catch (ParserConfigurationException e) {
                throw new SAXException(e);
            }
        }
        fDOMValidatorHandler = fDOMResultBuilder;
        fDOMResultBuilder.setDOMResult(result);
        fSchemaValidator.setDocumentHandler(fDOMResultBuilder);
    
private voidsetupEntityMap(org.w3c.dom.Document doc)
Extracts NamedNodeMap of entities. We need this to validate elements and attributes of type xs:ENTITY, xs:ENTITIES or types dervied from them.

        if (doc != null) {
            DocumentType docType = doc.getDoctype();
            if (docType != null) {
                fEntities = docType.getEntities();
                return;
            }
        }
        fEntities = null;
    
private booleanuseIsSameNode(org.w3c.dom.Node node)
Use isSameNode() for testing node identity if the DOM implementation supports DOM Level 3 core and it isn't the Xerces implementation.

        if (node instanceof NodeImpl) {
            return false;
        }
        Document doc = node.getNodeType() == Node.DOCUMENT_NODE 
            ? (Document) node : node.getOwnerDocument();
        return (doc != null && doc.getImplementation().hasFeature("Core", "3.0"));
    
public voidvalidate(javax.xml.transform.Source source, javax.xml.transform.Result result)

        if (result instanceof DOMResult || result == null) {
            final DOMSource domSource = (DOMSource) source;
            final DOMResult domResult = (DOMResult) result;
            Node node = domSource.getNode();
            fRoot = node;
            if (node != null) {
                fComponentManager.reset();
                fValidationManager.setEntityState(this);
                fDOMNamespaceContext.reset();
                String systemId = domSource.getSystemId();
                fXMLLocator.setLiteralSystemId(systemId);
                fXMLLocator.setExpandedSystemId(systemId);
                fErrorReporter.setDocumentLocator(fXMLLocator);
                try {
                    // regardless of what type of node this is, fire start and end document events
                    setupEntityMap((node.getNodeType() == Node.DOCUMENT_NODE) ? (Document) node : node.getOwnerDocument());
                    setupDOMResultHandler(domSource, domResult);
                    fSchemaValidator.startDocument(fXMLLocator, null, fDOMNamespaceContext, null);
                    validate(node);
                    fSchemaValidator.endDocument(null);
                }
                catch (XMLParseException e) {
                    throw Util.toSAXParseException(e);
                }
                catch (XNIException e) {
                    throw Util.toSAXException(e);
                }
                finally {
                    // Release references to application objects
                    fRoot = null;
                    fCurrentElement = null;
                    fEntities = null;
                    if (fDOMValidatorHandler != null) {
                        fDOMValidatorHandler.setDOMResult(null);
                    }
                }
            }
            return;
        }
        throw new IllegalArgumentException(JAXPValidationMessageFormatter.formatMessage(Locale.getDefault(), 
                "SourceResultMismatch", 
                new Object [] {source.getClass().getName(), result.getClass().getName()}));
    
private voidvalidate(org.w3c.dom.Node node)
Traverse the DOM and fire events to the schema validator.

        final Node top = node;
        final boolean useIsSameNode = useIsSameNode(top);
        // Performs a non-recursive traversal of the DOM. This
        // will avoid a stack overflow for DOMs with high depth.
        while (node != null) {
            beginNode(node);
            Node next = node.getFirstChild();
            while (next == null) {
                finishNode(node);           
                if (top == node) {
                    break;
                }
                next = node.getNextSibling();
                if (next == null) {
                    node = node.getParentNode();
                    if (node == null || ((useIsSameNode) ? 
                        top.isSameNode(node) : top == node)) {
                        if (node != null) {
                            finishNode(node);
                        }
                        next = null;
                        break;
                    }
                }
            }
            node = next;
        }