1 57 58 package com.sun.org.apache.xerces.internal.impl.dtd.models; 59 60 import com.sun.org.apache.xerces.internal.xni.QName; 61 import com.sun.org.apache.xerces.internal.impl.dtd.XMLContentSpec; 62 63 78 public class DFAContentModel 79 implements ContentModelValidator { 80 81 86 87 private static String fEpsilonString = "<<CMNODE_EPSILON>>"; 88 89 90 private static String fEOCString = "<<CMNODE_EOC>>"; 91 92 93 static { 94 fEpsilonString = fEpsilonString.intern(); 95 fEOCString = fEOCString.intern(); 96 } 97 98 100 101 private static final boolean DEBUG_VALIDATE_CONTENT = false; 102 103 107 108 110 116 private QName fElemMap[] = null; 117 118 122 private int fElemMapType[] = null; 123 124 125 private int fElemMapSize = 0; 126 127 128 private boolean fMixed; 129 130 134 private int fEOCPos = 0; 135 136 137 142 private boolean fFinalStateFlags[] = null; 143 144 149 private CMStateSet fFollowList[] = null; 150 151 157 private CMNode fHeadNode = null; 158 159 163 private int fLeafCount = 0; 164 165 169 private CMLeaf fLeafList[] = null; 170 171 172 private int fLeafListType[] = null; 173 174 176 180 182 194 private int fTransTable[][] = null; 195 196 200 private int fTransTableSize = 0; 201 202 210 private boolean fEmptyContentIsValid = false; 211 212 214 215 private QName fQName = new QName(); 216 217 221 222 226 234 235 public DFAContentModel(CMNode syntaxTree, int leafCount, boolean mixed) { 236 fLeafCount = leafCount; 239 240 241 fMixed = mixed; 243 244 buildDFA(syntaxTree); 254 } 255 256 260 283 public int validate(QName[] children, int offset, int length) { 284 285 if (DEBUG_VALIDATE_CONTENT) 286 System.out.println("DFAContentModel#validateContent"); 287 288 if (length == 0) { 302 if (DEBUG_VALIDATE_CONTENT) { 303 System.out.println("!!! no children"); 304 System.out.println("elemMap="+fElemMap); 305 for (int i = 0; i < fElemMap.length; i++) { 306 String uri = fElemMap[i].uri; 307 String localpart = fElemMap[i].localpart; 308 309 System.out.println("fElemMap["+i+"]="+uri+","+ 310 localpart+" ("+ 311 uri+", "+ 312 localpart+ 313 ')'); 314 315 } 316 System.out.println("EOCIndex="+fEOCString); 317 } 318 319 return fEmptyContentIsValid ? -1 : 0; 320 321 } 323 int curState = 0; 329 for (int childIndex = 0; childIndex < length; childIndex++) 330 { 331 final QName curElem = children[offset + childIndex]; 333 if (fMixed && curElem.localpart == null) { 335 continue; 336 } 337 338 int elemIndex = 0; 340 for (; elemIndex < fElemMapSize; elemIndex++) 341 { 342 int type = fElemMapType[elemIndex] & 0x0f ; 343 if (type == XMLContentSpec.CONTENTSPECNODE_LEAF) { 344 if (fElemMap[elemIndex].rawname == curElem.rawname) { 346 break; 347 } 348 } 349 else if (type == XMLContentSpec.CONTENTSPECNODE_ANY) { 350 String uri = fElemMap[elemIndex].uri; 351 if (uri == null || uri == curElem.uri) { 352 break; 353 } 354 } 355 else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) { 356 if (curElem.uri == null) { 357 break; 358 } 359 } 360 else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) { 361 if (fElemMap[elemIndex].uri != curElem.uri) { 362 break; 363 } 364 } 365 } 366 367 if (elemIndex == fElemMapSize) { 369 if (DEBUG_VALIDATE_CONTENT) { 370 System.out.println("!!! didn't find it"); 371 372 System.out.println("curElem : " +curElem ); 373 for (int i=0; i<fElemMapSize; i++) { 374 System.out.println("fElemMap["+i+"] = " +fElemMap[i] ); 375 System.out.println("fElemMapType["+i+"] = " +fElemMapType[i] ); 376 } 377 } 378 379 return childIndex; 380 } 381 382 curState = fTransTable[curState][elemIndex]; 387 388 if (curState == -1) { 390 if (DEBUG_VALIDATE_CONTENT) 391 System.out.println("!!! not a legal transition"); 392 return childIndex; 393 } 394 } 395 396 if (DEBUG_VALIDATE_CONTENT) 402 System.out.println("curState="+curState+", childCount="+length); 403 if (!fFinalStateFlags[curState]) 404 return length; 405 406 return -1; 408 } 410 411 415 422 private void buildDFA(CMNode syntaxTree) 423 { 424 453 464 465 fQName.setValues(null, fEOCString, fEOCString, null); 466 CMLeaf nodeEOC = new CMLeaf(fQName); 467 fHeadNode = new CMBinOp 468 ( 469 XMLContentSpec.CONTENTSPECNODE_SEQ 470 , syntaxTree 471 , nodeEOC 472 ); 473 474 fEOCPos = fLeafCount; 482 nodeEOC.setPosition(fLeafCount++); 483 484 fLeafList = new CMLeaf[fLeafCount]; 499 fLeafListType = new int[fLeafCount]; 500 postTreeBuildInit(fHeadNode, 0); 501 502 fFollowList = new CMStateSet[fLeafCount]; 508 for (int index = 0; index < fLeafCount; index++) 509 fFollowList[index] = new CMStateSet(fLeafCount); 510 calcFollowList(fHeadNode); 511 fElemMap = new QName[fLeafCount]; 523 fElemMapType = new int[fLeafCount]; 524 fElemMapSize = 0; 525 for (int outIndex = 0; outIndex < fLeafCount; outIndex++) 526 { 527 fElemMap[outIndex] = new QName(); 528 529 536 537 final QName element = fLeafList[outIndex].getElement(); 539 540 int inIndex = 0; 542 for (; inIndex < fElemMapSize; inIndex++) 543 { 544 if (fElemMap[inIndex].rawname == element.rawname) { 545 break; 546 } 547 } 548 549 if (inIndex == fElemMapSize) { 551 fElemMap[fElemMapSize].setValues(element); 552 fElemMapType[fElemMapSize] = fLeafListType[outIndex]; 553 fElemMapSize++; 554 } 555 } 556 567 568 int[] fLeafSorter = new int[fLeafCount + fElemMapSize]; 569 int fSortCount = 0; 570 571 for (int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) { 572 for (int leafIndex = 0; leafIndex < fLeafCount; leafIndex++) { 573 final QName leaf = fLeafList[leafIndex].getElement(); 574 final QName element = fElemMap[elemIndex]; 575 if (leaf.rawname == element.rawname) { 576 fLeafSorter[fSortCount++] = leafIndex; 577 } 578 } 579 fLeafSorter[fSortCount++] = -1; 580 } 581 582 583 584 int curArraySize = fLeafCount * 4; 598 CMStateSet[] statesToDo = new CMStateSet[curArraySize]; 599 fFinalStateFlags = new boolean[curArraySize]; 600 fTransTable = new int[curArraySize][]; 601 602 CMStateSet setT = fHeadNode.firstPos(); 608 609 int unmarkedState = 0; 618 int curState = 0; 619 620 fTransTable[curState] = makeDefStateList(); 625 statesToDo[curState] = setT; 626 curState++; 627 628 631 632 java.util.Hashtable stateTable = new java.util.Hashtable (); 633 634 635 636 while (unmarkedState < curState) 642 { 643 setT = statesToDo[unmarkedState]; 648 int[] transEntry = fTransTable[unmarkedState]; 649 650 fFinalStateFlags[unmarkedState] = setT.getBit(fEOCPos); 652 653 unmarkedState++; 655 656 CMStateSet newSet = null; 658 659 int sorterIndex = 0; 660 661 for (int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) 662 { 663 if (newSet == null) 670 newSet = new CMStateSet(fLeafCount); 671 else 672 newSet.zeroBits(); 673 674 675 int leafIndex = fLeafSorter[sorterIndex++]; 676 677 while (leafIndex != -1) { 678 if (setT.getBit(leafIndex)) 680 { 681 newSet.union(fFollowList[leafIndex]); 687 } 688 689 leafIndex = fLeafSorter[sorterIndex++]; 690 } 691 692 693 if (!newSet.isEmpty()) 698 { 699 704 705 Integer stateObj = (Integer )stateTable.get(newSet); 706 int stateIndex = (stateObj == null ? curState : stateObj.intValue()); 707 708 709 if (stateIndex == curState) 711 { 712 statesToDo[curState] = newSet; 718 fTransTable[curState] = makeDefStateList(); 719 720 721 stateTable.put(newSet, new Integer (curState)); 722 723 724 curState++; 726 727 newSet = null; 733 } 734 735 transEntry[elemIndex] = stateIndex; 742 743 if (curState == curArraySize) 745 { 746 final int newSize = (int)(curArraySize * 1.5); 752 CMStateSet[] newToDo = new CMStateSet[newSize]; 753 boolean[] newFinalFlags = new boolean[newSize]; 754 int[][] newTransTable = new int[newSize][]; 755 756 for (int expIndex = 0; expIndex < curArraySize; expIndex++) 758 { 759 newToDo[expIndex] = statesToDo[expIndex]; 760 newFinalFlags[expIndex] = fFinalStateFlags[expIndex]; 761 newTransTable[expIndex] = fTransTable[expIndex]; 762 } 763 764 curArraySize = newSize; 766 statesToDo = newToDo; 767 fFinalStateFlags = newFinalFlags; 768 fTransTable = newTransTable; 769 } 770 } 771 } 772 } 773 774 fEmptyContentIsValid = ((CMBinOp)fHeadNode).getLeft().isNullable(); 776 777 if (DEBUG_VALIDATE_CONTENT) 782 dumpTree(fHeadNode, 0); 783 fHeadNode = null; 784 fLeafList = null; 785 fFollowList = null; 786 787 } 788 789 796 private void calcFollowList(CMNode nodeCur) 797 { 798 if (nodeCur.type() == XMLContentSpec.CONTENTSPECNODE_CHOICE) 800 { 801 calcFollowList(((CMBinOp)nodeCur).getLeft()); 803 calcFollowList(((CMBinOp)nodeCur).getRight()); 804 } 805 else if (nodeCur.type() == XMLContentSpec.CONTENTSPECNODE_SEQ) 806 { 807 calcFollowList(((CMBinOp)nodeCur).getLeft()); 809 calcFollowList(((CMBinOp)nodeCur).getRight()); 810 811 final CMStateSet last = ((CMBinOp)nodeCur).getLeft().lastPos(); 817 final CMStateSet first = ((CMBinOp)nodeCur).getRight().firstPos(); 818 819 for (int index = 0; index < fLeafCount; index++) 825 { 826 if (last.getBit(index)) 827 fFollowList[index].union(first); 828 } 829 } 830 860 else if (nodeCur.type() == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE 861 || nodeCur.type() == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) 862 { 863 calcFollowList(((CMUniOp)nodeCur).getChild()); 865 866 final CMStateSet first = nodeCur.firstPos(); 871 final CMStateSet last = nodeCur.lastPos(); 872 873 for (int index = 0; index < fLeafCount; index++) 879 { 880 if (last.getBit(index)) 881 fFollowList[index].union(first); 882 } 883 } 884 885 else if (nodeCur.type() == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE) { 886 calcFollowList(((CMUniOp)nodeCur).getChild()); 888 } 889 890 } 891 892 900 private void dumpTree(CMNode nodeCur, int level) 901 { 902 for (int index = 0; index < level; index++) 903 System.out.print(" "); 904 905 int type = nodeCur.type(); 906 if ((type == XMLContentSpec.CONTENTSPECNODE_CHOICE) 907 || (type == XMLContentSpec.CONTENTSPECNODE_SEQ)) 908 { 909 if (type == XMLContentSpec.CONTENTSPECNODE_CHOICE) 910 System.out.print("Choice Node "); 911 else 912 System.out.print("Seq Node "); 913 914 if (nodeCur.isNullable()) 915 System.out.print("Nullable "); 916 917 System.out.print("firstPos="); 918 System.out.print(nodeCur.firstPos().toString()); 919 System.out.print(" lastPos="); 920 System.out.println(nodeCur.lastPos().toString()); 921 922 dumpTree(((CMBinOp)nodeCur).getLeft(), level+1); 923 dumpTree(((CMBinOp)nodeCur).getRight(), level+1); 924 } 925 else if (nodeCur.type() == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE) 926 { 927 System.out.print("Rep Node "); 928 929 if (nodeCur.isNullable()) 930 System.out.print("Nullable "); 931 932 System.out.print("firstPos="); 933 System.out.print(nodeCur.firstPos().toString()); 934 System.out.print(" lastPos="); 935 System.out.println(nodeCur.lastPos().toString()); 936 937 dumpTree(((CMUniOp)nodeCur).getChild(), level+1); 938 } 939 else if (nodeCur.type() == XMLContentSpec.CONTENTSPECNODE_LEAF) 940 { 941 System.out.print 942 ( 943 "Leaf: (pos=" 944 + ((CMLeaf)nodeCur).getPosition() 945 + "), " 946 + ((CMLeaf)nodeCur).getElement() 947 + "(elemIndex=" 948 + ((CMLeaf)nodeCur).getElement() 949 + ") " 950 ); 951 952 if (nodeCur.isNullable()) 953 System.out.print(" Nullable "); 954 955 System.out.print("firstPos="); 956 System.out.print(nodeCur.firstPos().toString()); 957 System.out.print(" lastPos="); 958 System.out.println(nodeCur.lastPos().toString()); 959 } 960 else 961 { 962 throw new RuntimeException ("ImplementationMessages.VAL_NIICM"); 963 } 964 } 965 966 967 972 private int[] makeDefStateList() 973 { 974 int[] retArray = new int[fElemMapSize]; 975 for (int index = 0; index < fElemMapSize; index++) 976 retArray[index] = -1; 977 return retArray; 978 } 979 980 981 private int postTreeBuildInit(CMNode nodeCur, int curIndex) 982 { 983 nodeCur.setMaxStates(fLeafCount); 985 986 if ((nodeCur.type() & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY || 988 (nodeCur.type() & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL || 989 (nodeCur.type() & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) { 990 QName qname = new QName(null, null, null, ((CMAny)nodeCur).getURI()); 992 fLeafList[curIndex] = new CMLeaf(qname, ((CMAny)nodeCur).getPosition()); 993 fLeafListType[curIndex] = nodeCur.type(); 994 curIndex++; 995 } 996 else if ((nodeCur.type() == XMLContentSpec.CONTENTSPECNODE_CHOICE) 997 || (nodeCur.type() == XMLContentSpec.CONTENTSPECNODE_SEQ)) 998 { 999 curIndex = postTreeBuildInit(((CMBinOp)nodeCur).getLeft(), curIndex); 1000 curIndex = postTreeBuildInit(((CMBinOp)nodeCur).getRight(), curIndex); 1001 } 1002 else if (nodeCur.type() == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE 1003 || nodeCur.type() == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE 1004 || nodeCur.type() == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE) 1005 { 1006 curIndex = postTreeBuildInit(((CMUniOp)nodeCur).getChild(), curIndex); 1007 } 1008 else if (nodeCur.type() == XMLContentSpec.CONTENTSPECNODE_LEAF) 1009 { 1010 final QName node = ((CMLeaf)nodeCur).getElement(); 1015 if (node.localpart != fEpsilonString) { 1016 fLeafList[curIndex] = (CMLeaf)nodeCur; 1017 fLeafListType[curIndex] = XMLContentSpec.CONTENTSPECNODE_LEAF; 1018 curIndex++; 1019 } 1020 } 1021 else 1022 { 1023 throw new RuntimeException ("ImplementationMessages.VAL_NIICM: type="+nodeCur.type()); 1024 } 1025 return curIndex; 1026 } 1027 1028} | Popular Tags |