Package com.sun.msv.schematron.verifier

Source Code of com.sun.msv.schematron.verifier.RelmesVerifier$SchematronVerifier

package com.sun.msv.schematron.verifier;

import com.sun.msv.schematron.grammar.SAction;
import com.sun.msv.schematron.grammar.SActions;
import com.sun.msv.schematron.grammar.SElementExp;
import com.sun.msv.schematron.grammar.SRule;
import com.sun.msv.schematron.util.DOMBuilder;
import com.sun.msv.verifier.DocumentDeclaration;
import com.sun.msv.verifier.IVerifier;
import com.sun.msv.verifier.ValidityViolation;
import com.sun.msv.verifier.Verifier;
import com.sun.msv.verifier.VerifierFilter;
import org.apache.xml.utils.PrefixResolverDefault;
import org.apache.xpath.XPathContext;
import org.relaxng.datatype.Datatype;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.ErrorHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.LocatorImpl;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

public class RelmesVerifier implements IVerifier {
       
        public RelmesVerifier( IVerifier core ) throws ParserConfigurationException {
                this.core = new VerifierFilter(core);
                this.core.setContentHandler(new SchematronVerifier());
        }
        public RelmesVerifier( DocumentDeclaration docDecl, ErrorHandler handler )
                                throws ParserConfigurationException {
                this(new Verifier(docDecl,handler));
        }
       
        /**
         * this object performs RELAX NG validation,
         * then pass type-information to the schematron checker.
         */
        private final VerifierFilter core;
       
        /**
         * this flag is set to true when all schematron validations are successful.
         */
        private boolean schematronValid;

        /** performs schematron validation. */
        class SchematronVerifier extends DOMBuilder {
               
        /**
         * ID -> value map. We can't trust DOM to do this for us.
         */
        private final Map idMap = new HashMap();
       
        XPathContext xctxt = new XPathContext();


                SchematronVerifier() throws ParserConfigurationException {}
               
                public void startElement( String ns, String local, String qname, Attributes atts ) throws SAXException {
                        super.startElement(ns,local,qname,atts);
                        locationMap.put( super.parent, new Loc(getLocator()) );
                       
                        Object o = getCurrentElementType();
                        if( o instanceof SElementExp ) {
//                              System.out.println("Schematron node found");
                                // memorize this node so that we can check it later.
                                checks.put( super.parent, o );
                        }
           
            // build ID map
            for( int i=0; i<atts.getLength(); i++ ) {
                if( "ID".equals(atts.getType(i)) ) {
                    // since there's no way to achieve this via DOM,
                    // we need to directly talk to the implementation.
                    try {
                        // Xerces?
                        ((org.apache.xerces.dom.CoreDocumentImpl)super.dom).putIdentifier(
                            atts.getValue(i), (Element)super.parent );
                    } catch( Throwable t ) {
                        // ignore any error. it wasn't Xerces.
                    }
                    try {
                        // Crimson?
                        ((org.apache.crimson.tree.ElementNode2)super.parent)
                            .setIdAttributeName(atts.getQName(i));
                    } catch( Throwable t ) {
                        // ignore any error. it wasn't Crimson.
                    }
                }
            }
                }
               
                /**
                 * a map from Element to Loc object.
                 * This map will be used to report the source of error.
                 */
                private final Map locationMap = new HashMap();
               
                /**
                 * a map from Node to SElementExp.
                 * These are checked later.
                 */
                private final Map checks = new HashMap();
               
                public void startDocument() throws SAXException {
                        super.startDocument();
                        checks.clear();
                        locationMap.clear();
                }
               
                public void endDocument() throws SAXException {
                        super.endDocument();
                        schematronValid = true;

                        try {
                                testNode(super.dom);
                        } catch( TransformerException e ) {
                                getErrorHandler().error( new ValidityViolation(
                                        null, "XPath error:"+e.getMessage(), null ) );
                                schematronValid = false;
                        }
                }
               
                /** SRule objects that are currently in effect. */
                private final Stack effectiveRules = new Stack();
               
                private void testNode( Node node ) throws SAXException, TransformerException {
                       
                        // if this node has the corresponding rule to be checked,
                        // push it to the stack.
                        // if we already have the same rule object, there is no need to
                        // add it twice.
                        SElementExp exp = (SElementExp)checks.get(node);
//                      System.out.println("node tested");
                        int numRulesAdded = 0;
                        if(exp!=null ) {
//                              System.out.println("rule added");
                                for( int i=0; i<exp.rules.length; i++ ) {
                                        if(!effectiveRules.contains(exp.rules)) {
                                                effectiveRules.push(exp.rules[i]);
                                                numRulesAdded++;
                                        }
                                }
                // if the element decl has any direction actions, run them now.
                testActions( exp.actions, node );
                        }
                       
                        // test effective rules against this node
                        int len = effectiveRules.size();
                        for( int i=0; i<len; i++ )
                                testRule( (SRule)effectiveRules.get(i), node );
                       
                        // recursively process children
                        if( node.getNodeType()==Node.ELEMENT_NODE ) {
                                Element e = (Element)node;
                                NamedNodeMap atts = e.getAttributes();
                                len = atts.getLength();
                                for( int i=0; i<len; i++ )
                                        testNode( atts.item(i) );
                        }
                       
                        NodeList children = node.getChildNodes();
                        len = children.getLength();
                        for( int i=0; i<len; i++ )
                                testNode( children.item(i) );
                       
                        // a rule is in effect only in itself or descendants.
                        for( ; numRulesAdded>0; numRulesAdded-- )
                                effectiveRules.pop();
                }
               
                /**
                 * tests the specified rule against the node.
                 */
                private void testRule( SRule rule, Node node )
                                        throws SAXException, TransformerException {
                       
                        if( !rule.matches(xctxt,node) ) return;
           
            testActions(rule,node);
        }
                   
                   
                private void testActions( SActions actions, Node node )
                throws SAXException, TransformerException {
//                      System.out.println("rule tested");
                       
                        PrefixResolverDefault resolver = new PrefixResolverDefault(node);

            synchronized(actions) {
                                // I'm not sure whether XPath object is thread-safe.
                                // so for precaution, synchronize it.
               
                // I'm not sure if XPathContextImpl is reusable,
                // so again just for precaution, we will create new ones each time
                               
                                for( int i=0; i<actions.asserts.length; i++ )
                    if (!actions.asserts[i].xpath.execute(
                        xctxt, node, resolver).bool())
                        reportError(node, actions.asserts[i]);
                                                       
                                for( int i=0; i<actions.reports.length; i++ )
                                        if(actions.reports[i].xpath.execute(
                                                xctxt, node, resolver ).bool() )
                                                reportError( node, actions.reports[i] );
                        }                                      
                }

                private void reportError( Node node, SAction action ) throws SAXException {
                        Loc loc = (Loc)locationMap.get(node);
            if( loc==null ) {
                if( node instanceof Attr ) {
                    reportError( ((Attr)node).getOwnerElement(), action );
                    return;
                }
                if( node.getParentNode()!=null ) {
                                    reportError( node.getParentNode(), action );
                                    return;
                }
                        }
                       
                        LocatorImpl src = new LocatorImpl();
            if(loc!=null) {
                            src.setLineNumber(loc.line);
                            src.setColumnNumber(loc.col);
            }
                        src.setSystemId(getLocator().getSystemId());
                        src.setPublicId(getLocator().getPublicId());
                       
                        schematronValid = false;
                        getErrorHandler().error( new ValidityViolation(
                                src, action.document, null ));
                }
        }
       
       
       
       
        public void setPanicMode(boolean v) {
                core.setPanicMode(v);
        }
        public boolean isValid() {
                return schematronValid && core.isValid();
        }
        public Object getCurrentElementType() {
                return core.getCurrentElementType();
        }
        public Datatype[] getLastCharacterType() {
                return core.getLastCharacterType();
        }
        public final Locator getLocator() {
                return core.getLocator();
        }
        public final ErrorHandler getErrorHandler() {
                return core.getErrorHandler();
        }
        public final void setErrorHandler( ErrorHandler handler ) {
                core.setErrorHandler(handler);
        }

       
       
       
       
       
       
    public void setDocumentLocator(Locator locator) {
                core.setDocumentLocator(locator);
    }

    public void startDocument() throws SAXException {
                core.startDocument();
    }

    public void endDocument() throws SAXException {
                core.endDocument();
    }

    public void startPrefixMapping( String prefix, String uri ) throws SAXException {
                core.startPrefixMapping(prefix, uri);
    }

    public void endPrefixMapping(String prefix) throws SAXException {
                core.endPrefixMapping(prefix);
    }

    public void startElement( String namespaceURI, String localName, String qName, Attributes atts ) throws SAXException {
                core.startElement(namespaceURI, localName, qName, atts);
    }

    public void endElement(     String namespaceURI, String localName, String qName ) throws SAXException {
                core.endElement(namespaceURI, localName, qName);
    }

    public void characters( char ch[], int start, int length ) throws SAXException {
                core.characters(ch, start, length);
    }

    public void ignorableWhitespace( char ch[], int start, int length ) throws SAXException {
                core.ignorableWhitespace(ch, start, length);
    }

    public void processingInstruction(String target, String data) throws SAXException {
                core.processingInstruction(target, data);
    }

    public void skippedEntity(String name) throws SAXException {
                core.skippedEntity(name);
    }
}
TOP

Related Classes of com.sun.msv.schematron.verifier.RelmesVerifier$SchematronVerifier

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.