1 16 17 package org.apache.xerces.impl.xs.models; 18 19 import org.apache.xerces.xni.QName; 20 import org.apache.xerces.impl.dtd.models.CMNode; 21 import org.apache.xerces.impl.dtd.models.CMStateSet; 22 import org.apache.xerces.impl.xs.SubstitutionGroupHandler; 23 import org.apache.xerces.impl.xs.XSElementDecl; 24 import org.apache.xerces.impl.xs.XSParticleDecl; 25 import org.apache.xerces.impl.xs.XSModelGroupImpl; 26 import org.apache.xerces.impl.xs.XSWildcardDecl; 27 import org.apache.xerces.impl.xs.XMLSchemaException; 28 import org.apache.xerces.impl.xs.XSConstraints; 29 30 import java.util.Vector ; 31 32 43 public class XSDFACM 44 implements XSCMValidator { 45 46 private static final boolean DEBUG = false; 50 51 53 55 56 private static final boolean DEBUG_VALIDATE_CONTENT = false; 57 58 62 69 private Object fElemMap[] = null; 70 71 75 private int fElemMapType[] = null; 76 77 80 private int fElemMapId[] = null; 81 82 83 private int fElemMapSize = 0; 84 85 90 private boolean fFinalStateFlags[] = null; 91 92 97 private CMStateSet fFollowList[] = null; 98 99 105 private CMNode fHeadNode = null; 106 107 111 private int fLeafCount = 0; 112 113 117 private XSCMLeaf fLeafList[] = null; 118 119 120 private int fLeafListType[] = null; 121 122 134 private int fTransTable[][] = null; 135 136 140 private int fTransTableSize = 0; 141 142 144 148 156 157 public XSDFACM(CMNode syntaxTree, int leafCount) { 158 159 fLeafCount = leafCount; 161 162 168 178 if(DEBUG_VALIDATE_CONTENT) { 179 XSDFACM.time -= System.currentTimeMillis(); 180 } 181 182 buildDFA(syntaxTree); 183 184 if(DEBUG_VALIDATE_CONTENT) { 185 XSDFACM.time += System.currentTimeMillis(); 186 System.out.println("DFA build: " + XSDFACM.time + "ms"); 187 } 188 } 189 190 private static long time = 0; 191 192 196 203 public boolean isFinalState (int state) { 204 return (state < 0)? false : 205 fFinalStateFlags[state]; 206 } 207 208 222 public Object oneTransition(QName curElem, int[] state, SubstitutionGroupHandler subGroupHandler) { 223 int curState = state[0]; 224 225 if(curState == XSCMValidator.FIRST_ERROR || curState == XSCMValidator.SUBSEQUENT_ERROR) { 226 if(curState == XSCMValidator.FIRST_ERROR) 229 state[0] = XSCMValidator.SUBSEQUENT_ERROR; 230 231 return findMatchingDecl(curElem, subGroupHandler); 232 } 233 234 int nextState = 0; 235 int elemIndex = 0; 236 Object matchingDecl = null; 237 238 for (; elemIndex < fElemMapSize; elemIndex++) { 239 nextState = fTransTable[curState][elemIndex]; 240 if (nextState == -1) 241 continue; 242 int type = fElemMapType[elemIndex] ; 243 if (type == XSParticleDecl.PARTICLE_ELEMENT) { 244 matchingDecl = subGroupHandler.getMatchingElemDecl(curElem, (XSElementDecl)fElemMap[elemIndex]); 245 if (matchingDecl != null) { 246 break; 247 } 248 } 249 else if (type == XSParticleDecl.PARTICLE_WILDCARD) { 250 if(((XSWildcardDecl)fElemMap[elemIndex]).allowNamespace(curElem.uri)) { 251 matchingDecl = fElemMap[elemIndex]; 252 break; 253 } 254 } 255 } 256 257 if (elemIndex == fElemMapSize) { 260 state[1] = state[0]; 261 state[0] = XSCMValidator.FIRST_ERROR; 262 return findMatchingDecl(curElem, subGroupHandler); 263 } 264 265 state[0] = nextState; 266 return matchingDecl; 267 } 269 Object findMatchingDecl(QName curElem, SubstitutionGroupHandler subGroupHandler) { 270 Object matchingDecl = null; 271 272 for (int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) { 273 int type = fElemMapType[elemIndex] ; 274 if (type == XSParticleDecl.PARTICLE_ELEMENT) { 275 matchingDecl = subGroupHandler.getMatchingElemDecl(curElem, (XSElementDecl)fElemMap[elemIndex]); 276 if (matchingDecl != null) { 277 return matchingDecl; 278 } 279 } 280 else if (type == XSParticleDecl.PARTICLE_WILDCARD) { 281 if(((XSWildcardDecl)fElemMap[elemIndex]).allowNamespace(curElem.uri)) 282 return fElemMap[elemIndex]; 283 } 284 } 285 286 return null; 287 } 288 289 public int[] startContentModel() { 291 int[] val = new int[2]; 292 val[0] = 0; 293 return val; 294 } 296 public boolean endContentModel(int[] state) { 298 return fFinalStateFlags[state[0]]; 299 } 301 304 308 315 private void buildDFA(CMNode syntaxTree) { 316 345 356 357 int EOCPos = fLeafCount; 365 XSCMLeaf nodeEOC = new XSCMLeaf(XSParticleDecl.PARTICLE_ELEMENT, null, -1, fLeafCount++); 366 fHeadNode = new XSCMBinOp( 367 XSModelGroupImpl.MODELGROUP_SEQUENCE, 368 syntaxTree, 369 nodeEOC 370 ); 371 372 fLeafList = new XSCMLeaf[fLeafCount]; 387 fLeafListType = new int[fLeafCount]; 388 postTreeBuildInit(fHeadNode); 389 390 fFollowList = new CMStateSet[fLeafCount]; 396 for (int index = 0; index < fLeafCount; index++) 397 fFollowList[index] = new CMStateSet(fLeafCount); 398 calcFollowList(fHeadNode); 399 fElemMap = new Object [fLeafCount]; 411 fElemMapType = new int[fLeafCount]; 412 fElemMapId = new int[fLeafCount]; 413 fElemMapSize = 0; 414 for (int outIndex = 0; outIndex < fLeafCount; outIndex++) { 415 fElemMap[outIndex] = null; 418 419 int inIndex = 0; 420 final int id = fLeafList[outIndex].getParticleId(); 421 for (; inIndex < fElemMapSize; inIndex++) { 422 if (id == fElemMapId[inIndex]) 423 break; 424 } 425 426 if (inIndex == fElemMapSize) { 428 fElemMap[fElemMapSize] = fLeafList[outIndex].getLeaf(); 429 fElemMapType[fElemMapSize] = fLeafListType[outIndex]; 430 fElemMapId[fElemMapSize] = id; 431 fElemMapSize++; 432 } 433 } 434 435 if (DEBUG) { 438 if (fElemMapId[fElemMapSize-1] != -1) 439 System.err.println("interal error in DFA: last element is not EOC."); 440 } 441 fElemMapSize--; 442 443 448 449 int[] fLeafSorter = new int[fLeafCount + fElemMapSize]; 450 int fSortCount = 0; 451 452 for (int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) { 453 final int id = fElemMapId[elemIndex]; 454 for (int leafIndex = 0; leafIndex < fLeafCount; leafIndex++) { 455 if (id == fLeafList[leafIndex].getParticleId()) 456 fLeafSorter[fSortCount++] = leafIndex; 457 } 458 fLeafSorter[fSortCount++] = -1; 459 } 460 461 462 463 int curArraySize = fLeafCount * 4; 477 CMStateSet[] statesToDo = new CMStateSet[curArraySize]; 478 fFinalStateFlags = new boolean[curArraySize]; 479 fTransTable = new int[curArraySize][]; 480 481 CMStateSet setT = fHeadNode.firstPos(); 487 488 int unmarkedState = 0; 497 int curState = 0; 498 499 fTransTable[curState] = makeDefStateList(); 504 statesToDo[curState] = setT; 505 curState++; 506 507 510 511 java.util.Hashtable stateTable = new java.util.Hashtable (); 512 513 514 515 while (unmarkedState < curState) { 521 setT = statesToDo[unmarkedState]; 526 int[] transEntry = fTransTable[unmarkedState]; 527 528 fFinalStateFlags[unmarkedState] = setT.getBit(EOCPos); 530 531 unmarkedState++; 533 534 CMStateSet newSet = null; 536 537 int sorterIndex = 0; 538 539 for (int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) { 540 if (newSet == null) 547 newSet = new CMStateSet(fLeafCount); 548 else 549 newSet.zeroBits(); 550 551 552 int leafIndex = fLeafSorter[sorterIndex++]; 553 554 while (leafIndex != -1) { 555 if (setT.getBit(leafIndex)) { 557 newSet.union(fFollowList[leafIndex]); 563 } 564 565 leafIndex = fLeafSorter[sorterIndex++]; 566 } 567 568 569 if (!newSet.isEmpty()) { 574 579 580 Integer stateObj = (Integer )stateTable.get(newSet); 581 int stateIndex = (stateObj == null ? curState : stateObj.intValue()); 582 583 584 if (stateIndex == curState) { 586 statesToDo[curState] = newSet; 592 fTransTable[curState] = makeDefStateList(); 593 594 595 stateTable.put(newSet, new Integer (curState)); 596 597 598 curState++; 600 601 newSet = null; 607 } 608 609 transEntry[elemIndex] = stateIndex; 616 617 if (curState == curArraySize) { 619 final int newSize = (int)(curArraySize * 1.5); 625 CMStateSet[] newToDo = new CMStateSet[newSize]; 626 boolean[] newFinalFlags = new boolean[newSize]; 627 int[][] newTransTable = new int[newSize][]; 628 629 for (int expIndex = 0; expIndex < curArraySize; expIndex++) { 631 newToDo[expIndex] = statesToDo[expIndex]; 632 newFinalFlags[expIndex] = fFinalStateFlags[expIndex]; 633 newTransTable[expIndex] = fTransTable[expIndex]; 634 } 635 636 curArraySize = newSize; 638 statesToDo = newToDo; 639 fFinalStateFlags = newFinalFlags; 640 fTransTable = newTransTable; 641 } 642 } 643 } 644 } 645 646 if (DEBUG_VALIDATE_CONTENT) 651 dumpTree(fHeadNode, 0); 652 fHeadNode = null; 653 fLeafList = null; 654 fFollowList = null; 655 fLeafListType = null; 656 fElemMapId = null; 657 } 658 659 666 private void calcFollowList(CMNode nodeCur) { 667 if (nodeCur.type() == XSModelGroupImpl.MODELGROUP_CHOICE) { 669 calcFollowList(((XSCMBinOp)nodeCur).getLeft()); 671 calcFollowList(((XSCMBinOp)nodeCur).getRight()); 672 } 673 else if (nodeCur.type() == XSModelGroupImpl.MODELGROUP_SEQUENCE) { 674 calcFollowList(((XSCMBinOp)nodeCur).getLeft()); 676 calcFollowList(((XSCMBinOp)nodeCur).getRight()); 677 678 final CMStateSet last = ((XSCMBinOp)nodeCur).getLeft().lastPos(); 684 final CMStateSet first = ((XSCMBinOp)nodeCur).getRight().firstPos(); 685 686 for (int index = 0; index < fLeafCount; index++) { 692 if (last.getBit(index)) 693 fFollowList[index].union(first); 694 } 695 } 696 else if (nodeCur.type() == XSParticleDecl.PARTICLE_ZERO_OR_MORE 697 || nodeCur.type() == XSParticleDecl.PARTICLE_ONE_OR_MORE) { 698 calcFollowList(((XSCMUniOp)nodeCur).getChild()); 700 701 final CMStateSet first = nodeCur.firstPos(); 706 final CMStateSet last = nodeCur.lastPos(); 707 708 for (int index = 0; index < fLeafCount; index++) { 714 if (last.getBit(index)) 715 fFollowList[index].union(first); 716 } 717 } 718 719 else if (nodeCur.type() == XSParticleDecl.PARTICLE_ZERO_OR_ONE) { 720 calcFollowList(((XSCMUniOp)nodeCur).getChild()); 722 } 723 724 } 725 726 734 private void dumpTree(CMNode nodeCur, int level) { 735 for (int index = 0; index < level; index++) 736 System.out.print(" "); 737 738 int type = nodeCur.type(); 739 740 switch(type ) { 741 742 case XSModelGroupImpl.MODELGROUP_CHOICE: 743 case XSModelGroupImpl.MODELGROUP_SEQUENCE: { 744 if (type == XSModelGroupImpl.MODELGROUP_CHOICE) 745 System.out.print("Choice Node "); 746 else 747 System.out.print("Seq Node "); 748 749 if (nodeCur.isNullable()) 750 System.out.print("Nullable "); 751 752 System.out.print("firstPos="); 753 System.out.print(nodeCur.firstPos().toString()); 754 System.out.print(" lastPos="); 755 System.out.println(nodeCur.lastPos().toString()); 756 757 dumpTree(((XSCMBinOp)nodeCur).getLeft(), level+1); 758 dumpTree(((XSCMBinOp)nodeCur).getRight(), level+1); 759 break; 760 } 761 case XSParticleDecl.PARTICLE_ZERO_OR_MORE: 762 case XSParticleDecl.PARTICLE_ONE_OR_MORE: 763 case XSParticleDecl.PARTICLE_ZERO_OR_ONE: { 764 System.out.print("Rep Node "); 765 766 if (nodeCur.isNullable()) 767 System.out.print("Nullable "); 768 769 System.out.print("firstPos="); 770 System.out.print(nodeCur.firstPos().toString()); 771 System.out.print(" lastPos="); 772 System.out.println(nodeCur.lastPos().toString()); 773 774 dumpTree(((XSCMUniOp)nodeCur).getChild(), level+1); 775 break; 776 } 777 case XSParticleDecl.PARTICLE_ELEMENT: { 778 System.out.print 779 ( 780 "Leaf: (pos=" 781 + ((XSCMLeaf)nodeCur).getPosition() 782 + "), " 783 + "(elemIndex=" 784 + ((XSCMLeaf)nodeCur).getLeaf() 785 + ") " 786 ); 787 788 if (nodeCur.isNullable()) 789 System.out.print(" Nullable "); 790 791 System.out.print("firstPos="); 792 System.out.print(nodeCur.firstPos().toString()); 793 System.out.print(" lastPos="); 794 System.out.println(nodeCur.lastPos().toString()); 795 break; 796 } 797 case XSParticleDecl.PARTICLE_WILDCARD: 798 System.out.print("Any Node: "); 799 800 System.out.print("firstPos="); 801 System.out.print(nodeCur.firstPos().toString()); 802 System.out.print(" lastPos="); 803 System.out.println(nodeCur.lastPos().toString()); 804 break; 805 default: { 806 throw new RuntimeException ("ImplementationMessages.VAL_NIICM"); 807 } 808 } 809 810 } 811 812 813 818 private int[] makeDefStateList() 819 { 820 int[] retArray = new int[fElemMapSize]; 821 for (int index = 0; index < fElemMapSize; index++) 822 retArray[index] = -1; 823 return retArray; 824 } 825 826 827 private void postTreeBuildInit(CMNode nodeCur) throws RuntimeException { 828 nodeCur.setMaxStates(fLeafCount); 830 831 XSCMLeaf leaf = null; 832 int pos = 0; 833 if (nodeCur.type() == XSParticleDecl.PARTICLE_WILDCARD) { 835 leaf = (XSCMLeaf)nodeCur; 836 pos = leaf.getPosition(); 837 fLeafList[pos] = leaf; 838 fLeafListType[pos] = XSParticleDecl.PARTICLE_WILDCARD; 839 } 840 else if ((nodeCur.type() == XSModelGroupImpl.MODELGROUP_CHOICE) || 841 (nodeCur.type() == XSModelGroupImpl.MODELGROUP_SEQUENCE)) { 842 postTreeBuildInit(((XSCMBinOp)nodeCur).getLeft()); 843 postTreeBuildInit(((XSCMBinOp)nodeCur).getRight()); 844 } 845 else if (nodeCur.type() == XSParticleDecl.PARTICLE_ZERO_OR_MORE || 846 nodeCur.type() == XSParticleDecl.PARTICLE_ONE_OR_MORE || 847 nodeCur.type() == XSParticleDecl.PARTICLE_ZERO_OR_ONE) { 848 postTreeBuildInit(((XSCMUniOp)nodeCur).getChild()); 849 } 850 else if (nodeCur.type() == XSParticleDecl.PARTICLE_ELEMENT) { 851 leaf = (XSCMLeaf)nodeCur; 854 pos = leaf.getPosition(); 855 fLeafList[pos] = leaf; 856 fLeafListType[pos] = XSParticleDecl.PARTICLE_ELEMENT; 857 } 858 else { 859 throw new RuntimeException ("ImplementationMessages.VAL_NIICM"); 860 } 861 } 862 863 869 public boolean checkUniqueParticleAttribution(SubstitutionGroupHandler subGroupHandler) throws XMLSchemaException { 870 byte conflictTable[][] = new byte[fElemMapSize][fElemMapSize]; 875 876 for (int i = 0; i < fTransTable.length && fTransTable[i] != null; i++) { 878 for (int j = 0; j < fElemMapSize; j++) { 879 for (int k = j+1; k < fElemMapSize; k++) { 880 if (fTransTable[i][j] != -1 && 881 fTransTable[i][k] != -1) { 882 if (conflictTable[j][k] == 0) { 883 conflictTable[j][k] = XSConstraints.overlapUPA 884 (fElemMap[j],fElemMap[k], 885 subGroupHandler) ? 886 (byte)1 : (byte)-1; 887 } 888 } 889 } 890 } 891 } 892 893 for (int i = 0; i < fElemMapSize; i++) { 895 for (int j = 0; j < fElemMapSize; j++) { 896 if (conflictTable[i][j] == 1) { 897 throw new XMLSchemaException("cos-nonambig", new Object []{fElemMap[i].toString(), 901 fElemMap[j].toString()}); 902 } 903 } 904 } 905 906 for (int i = 0; i < fElemMapSize; i++) { 909 if (fElemMapType[i] == XSParticleDecl.PARTICLE_WILDCARD) { 910 XSWildcardDecl wildcard = (XSWildcardDecl)fElemMap[i]; 911 if (wildcard.fType == XSWildcardDecl.NSCONSTRAINT_LIST || 912 wildcard.fType == XSWildcardDecl.NSCONSTRAINT_NOT) { 913 return true; 914 } 915 } 916 } 917 918 return false; 919 } 920 921 930 public Vector whatCanGoHere(int[] state) { 931 int curState = state[0]; 932 if (curState < 0) 933 curState = state[1]; 934 935 Vector ret = new Vector (); 936 for (int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) { 937 if (fTransTable[curState][elemIndex] != -1) 938 ret.addElement(fElemMap[elemIndex]); 939 } 940 return ret; 941 } 942 943 } | Popular Tags |