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 + -
显示快捷键?