xsdfacm.java

来自「JAVA 所有包」· Java 代码 · 共 970 行 · 第 1/3 页

JAVA
970
字号
/* * Copyright 1999-2004 The Apache Software Foundation. *  * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *  *      http://www.apache.org/licenses/LICENSE-2.0 *  * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.sun.org.apache.xerces.internal.impl.xs.models;import com.sun.org.apache.xerces.internal.xni.QName;import com.sun.org.apache.xerces.internal.impl.dtd.models.CMNode;import com.sun.org.apache.xerces.internal.impl.dtd.models.CMStateSet;import com.sun.org.apache.xerces.internal.impl.xs.SubstitutionGroupHandler;import com.sun.org.apache.xerces.internal.impl.xs.XSElementDecl;import com.sun.org.apache.xerces.internal.impl.xs.XSParticleDecl;import com.sun.org.apache.xerces.internal.impl.xs.XSModelGroupImpl;import com.sun.org.apache.xerces.internal.impl.xs.XSWildcardDecl;import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaException;import com.sun.org.apache.xerces.internal.impl.xs.XSConstraints;import java.util.Vector;/** * DFAContentModel is the implementation of XSCMValidator that does * all of the non-trivial element content validation. This class does * the conversion from the regular expression to the DFA that * it then uses in its validation algorithm. * * @xerces.internal  * * @author Neil Graham, IBM * @version $Id: XSDFACM.java,v 1.4 2006/07/19 22:39:36 spericas Exp $ */public class XSDFACM    implements XSCMValidator {    //    // Constants    //    private static final boolean DEBUG = false;    // special strings    // debugging    /** Set to true to debug content model validation. */    private static final boolean DEBUG_VALIDATE_CONTENT = false;    //    // Data    //    /**     * This is the map of unique input symbol elements to indices into     * each state's per-input symbol transition table entry. This is part     * of the built DFA information that must be kept around to do the     * actual validation.  Note tat since either XSElementDecl or XSParticleDecl object     * can live here, we've got to use an Object.     */    private Object fElemMap[] = null;    /**     * This is a map of whether the element map contains information     * related to ANY models.     */    private int fElemMapType[] = null;    /**     * id of the unique input symbol     */    private int fElemMapId[] = null;        /** The element map size. */    private int fElemMapSize = 0;    /**     * This is an array of booleans, one per state (there are     * fTransTableSize states in the DFA) that indicates whether that     * state is a final state.     */    private boolean fFinalStateFlags[] = null;    /**     * The list of follow positions for each NFA position (i.e. for each     * non-epsilon leaf node.) This is only used during the building of     * the DFA, and is let go afterwards.     */    private CMStateSet fFollowList[] = null;    /**     * This is the head node of our intermediate representation. It is     * only non-null during the building of the DFA (just so that it     * does not have to be passed all around.) Once the DFA is built,     * this is no longer required so its nulled out.     */    private CMNode fHeadNode = null;    /**     * The count of leaf nodes. This is an important number that set some     * limits on the sizes of data structures in the DFA process.     */    private int fLeafCount = 0;    /**     * An array of non-epsilon leaf nodes, which is used during the DFA     * build operation, then dropped.     */    private XSCMLeaf fLeafList[] = null;    /** Array mapping ANY types to the leaf list. */    private int fLeafListType[] = null;    /**     * This is the transition table that is the main by product of all     * of the effort here. It is an array of arrays of ints. The first     * dimension is the number of states we end up with in the DFA. The     * second dimensions is the number of unique elements in the content     * model (fElemMapSize). Each entry in the second dimension indicates     * the new state given that input for the first dimension's start     * state.     * <p>     * The fElemMap array handles mapping from element indexes to     * positions in the second dimension of the transition table.     */    private int fTransTable[][] = null;    /**     * The number of valid entries in the transition table, and in the other     * related tables such as fFinalStateFlags.     */    private int fTransTableSize = 0;        private int fOneTransitionCounter = 0;        private Object fUserData;    // temp variables    //    // Constructors    //    /**     * Constructs a DFA content model.     *     * @param syntaxTree    The syntax tree of the content model.     * @param leafCount     The number of leaves.     *     * @exception RuntimeException Thrown if DFA can't be built.     */   public XSDFACM(CMNode syntaxTree, int leafCount) {           // Store away our index and pools in members        fLeafCount = leafCount;                fUserData = syntaxTree.getUserData();        //        //  Create some string pool indexes that represent the names of some        //  magical nodes in the syntax tree.        //  (already done in static initialization...        //        //        //  Ok, so lets grind through the building of the DFA. This method        //  handles the high level logic of the algorithm, but it uses a        //  number of helper classes to do its thing.        //        //  In order to avoid having hundreds of references to the error and        //  string handlers around, this guy and all of his helper classes        //  just throw a simple exception and we then pass it along.        //        if(DEBUG_VALIDATE_CONTENT) {            XSDFACM.time -= System.currentTimeMillis();        }        buildDFA(syntaxTree);        if(DEBUG_VALIDATE_CONTENT) {            XSDFACM.time += System.currentTimeMillis();            System.out.println("DFA build: " + XSDFACM.time + "ms");        }    }    private static long time = 0;    //    // XSCMValidator methods    //        /**     * Return the number of times the <code>oneTransition()</code> method      * was called, resulting on the DFA to move into a non-error state.      * This is used to check the minOccurs and maxOccurs bounds using a      * constant space algorithm.     */     public int getOneTransitionCounter() {        return fOneTransitionCounter;    }        /**     * Allows the user to get arbitrary data originally set on the content      * model node used to create this DFA.     */    public Object getUserData() {        return fUserData;    }    /**     * check whether the given state is one of the final states     *     * @param state       the state to check     *     * @return whether it's a final state     */    public boolean isFinalState (int state) {        return (state < 0)? false :            fFinalStateFlags[state];    }    /**     * one transition only     *     * @param curElem The current element's QName     * @param state stack to store the previous state     * @param subGroupHandler the substitution group handler     *     * @return  null if transition is invalid; otherwise the Object corresponding to the     *      XSElementDecl or XSWildcardDecl identified.  Also, the     *      state array will be modified to include the new state; this so that the validator can     *      store it away.     *     * @exception RuntimeException thrown on error     */    public Object oneTransition(QName curElem, int[] state, SubstitutionGroupHandler subGroupHandler) {        int curState = state[0];        if(curState == XSCMValidator.FIRST_ERROR || curState == XSCMValidator.SUBSEQUENT_ERROR) {            // there was an error last time; so just go find correct Object in fElemmMap.            // ... after resetting state[0].            if(curState == XSCMValidator.FIRST_ERROR)                state[0] = XSCMValidator.SUBSEQUENT_ERROR;            return findMatchingDecl(curElem, subGroupHandler);        }        int nextState = 0;        int elemIndex = 0;        Object matchingDecl = null;        for (; elemIndex < fElemMapSize; elemIndex++) {            nextState = fTransTable[curState][elemIndex];            if (nextState == -1)                continue;            int type = fElemMapType[elemIndex] ;            if (type == XSParticleDecl.PARTICLE_ELEMENT) {                matchingDecl = subGroupHandler.getMatchingElemDecl(curElem, (XSElementDecl)fElemMap[elemIndex]);                if (matchingDecl != null) {                    break;                }            }            else if (type == XSParticleDecl.PARTICLE_WILDCARD) {                if(((XSWildcardDecl)fElemMap[elemIndex]).allowNamespace(curElem.uri)) {                    matchingDecl = fElemMap[elemIndex];                    break;                }            }        }        // if we still can't find a match, set the state to first_error        // and return null        if (elemIndex == fElemMapSize) {            state[1] = state[0];            state[0] = XSCMValidator.FIRST_ERROR;            return findMatchingDecl(curElem, subGroupHandler);        }        fOneTransitionCounter++;        state[0] = nextState;        return matchingDecl;    } // oneTransition(QName, int[], SubstitutionGroupHandler):  Object    Object findMatchingDecl(QName curElem, SubstitutionGroupHandler subGroupHandler) {        Object matchingDecl = null;        for (int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) {            int type = fElemMapType[elemIndex] ;            if (type == XSParticleDecl.PARTICLE_ELEMENT) {                matchingDecl = subGroupHandler.getMatchingElemDecl(curElem, (XSElementDecl)fElemMap[elemIndex]);                if (matchingDecl != null) {                    return matchingDecl;                }            }            else if (type == XSParticleDecl.PARTICLE_WILDCARD) {                if(((XSWildcardDecl)fElemMap[elemIndex]).allowNamespace(curElem.uri))                    return fElemMap[elemIndex];            }        }        return null;    }    // This method returns the start states of the content model.    public int[] startContentModel() {        int[] val = new int[2];        val[0] = 0;        fOneTransitionCounter = 0;      // reset transition counter        return val;    } // startContentModel():int[]    // this method returns whether the last state was a valid final state    public boolean endContentModel(int[] state) {        return fFinalStateFlags[state[0]];

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?