1 16 package org.apache.xerces.xpointer; 17 18 import java.util.Hashtable ; 19 20 import org.apache.xerces.impl.XMLErrorReporter; 21 import org.apache.xerces.util.SymbolTable; 22 import org.apache.xerces.util.XMLChar; 23 import org.apache.xerces.xni.Augmentations; 24 import org.apache.xerces.xni.QName; 25 import org.apache.xerces.xni.XMLAttributes; 26 import org.apache.xerces.xni.XNIException; 27 import org.apache.xerces.xni.parser.XMLErrorHandler; 28 29 39 class ElementSchemePointer implements XPointerPart { 40 41 43 private String fSchemeName; 45 46 private String fSchemeData; 48 49 private String fShortHandPointerName; 51 52 private boolean fIsResolveElement = false; 56 57 private boolean fIsElementFound = false; 59 60 private boolean fWasOnlyEmptyElementFound = false; 62 63 boolean fIsShortHand = false; 65 66 int fFoundDepth = 0; 68 69 private int fChildSequence[]; 71 72 private int fCurrentChildPosition = 1; 74 75 private int fCurrentChildDepth = 0; 77 78 private int fCurrentChildSequence[];; 80 81 private boolean fIsFragmentResolved = false; 83 84 private ShortHandPointer fShortHandPointer; 86 87 protected XMLErrorReporter fErrorReporter; 89 90 protected XMLErrorHandler fErrorHandler; 92 93 private SymbolTable fSymbolTable; 95 96 public ElementSchemePointer() { 100 } 101 102 public ElementSchemePointer(SymbolTable symbolTable) { 103 fSymbolTable = symbolTable; 104 } 105 106 public ElementSchemePointer(SymbolTable symbolTable, 107 XMLErrorReporter errorReporter) { 108 fSymbolTable = symbolTable; 109 fErrorReporter = errorReporter; 110 } 111 112 116 122 public void parseXPointer(String xpointer) throws XNIException { 123 124 init(); 126 127 final Tokens tokens = new Tokens(fSymbolTable); 129 130 Scanner scanner = new Scanner(fSymbolTable) { 132 protected void addToken(Tokens tokens, int token) 133 throws XNIException { 134 if (token == Tokens.XPTRTOKEN_ELEM_CHILD 135 || token == Tokens.XPTRTOKEN_ELEM_NCNAME) { 136 super.addToken(tokens, token); 137 return; 138 } 139 reportError("InvalidElementSchemeToken", new Object [] { tokens 140 .getTokenString(token) }); 141 } 142 }; 143 144 int length = xpointer.length(); 146 boolean success = scanner.scanExpr(fSymbolTable, tokens, xpointer, 0, 147 length); 148 149 if (!success) { 150 reportError("InvalidElementSchemeXPointer", 151 new Object [] { xpointer }); 152 } 153 154 int tmpChildSequence[] = new int[tokens.getTokenCount() / 2 + 1]; 157 158 int i = 0; 160 161 while (tokens.hasMore()) { 163 int token = tokens.nextToken(); 164 165 switch (token) { 166 case Tokens.XPTRTOKEN_ELEM_NCNAME: { 167 169 token = tokens.nextToken(); 171 fShortHandPointerName = tokens.getTokenString(token); 172 173 fShortHandPointer = new ShortHandPointer(fSymbolTable); 175 fShortHandPointer.setSchemeName(fShortHandPointerName); 176 177 break; 178 } 179 case Tokens.XPTRTOKEN_ELEM_CHILD: { 180 tmpChildSequence[i] = tokens.nextToken(); 181 i++; 182 183 break; 184 } 185 default: 186 reportError("InvalidElementSchemeXPointer", 187 new Object [] { xpointer }); 188 } 189 } 190 191 fChildSequence = new int[i]; 193 fCurrentChildSequence = new int[i]; 194 System.arraycopy(tmpChildSequence, 0, fChildSequence, 0, i); 195 196 } 197 198 202 public String getSchemeName() { 203 return fSchemeName; 204 } 205 206 211 public String getSchemeData() { 212 return fSchemeData; 213 } 214 215 220 public void setSchemeName(String schemeName) { 221 fSchemeName = schemeName; 222 223 } 224 225 230 public void setSchemeData(String schemeData) { 231 fSchemeData = schemeData; 232 } 233 234 241 public boolean resolveXPointer(QName element, XMLAttributes attributes, 242 Augmentations augs, int event) throws XNIException { 243 244 boolean isShortHandPointerResolved = false; 245 246 248 if (fShortHandPointerName != null) { 250 isShortHandPointerResolved = fShortHandPointer.resolveXPointer( 252 element, attributes, augs, event); 253 if (isShortHandPointerResolved) { 254 fIsResolveElement = true; 255 fIsShortHand = true; 256 } else { 257 fIsResolveElement = false; 258 } 259 } else { 260 fIsResolveElement = true; 261 } 262 263 if (fChildSequence.length > 0) { 266 fIsFragmentResolved = matchChildSequence(element, event); 267 } else if (isShortHandPointerResolved && fChildSequence.length <= 0) { 268 fIsFragmentResolved = isShortHandPointerResolved; 270 } else { 271 fIsFragmentResolved = false; 272 } 273 274 return fIsFragmentResolved; 275 } 276 277 286 protected boolean matchChildSequence(QName element, int event) 287 throws XNIException { 288 289 if (fCurrentChildDepth >= fCurrentChildSequence.length) { 291 int tmpCurrentChildSequence[] = new int[fCurrentChildSequence.length]; 292 System.arraycopy(fCurrentChildSequence, 0, tmpCurrentChildSequence, 293 0, fCurrentChildSequence.length); 294 295 fCurrentChildSequence = new int[fCurrentChildDepth * 2]; 297 System.arraycopy(tmpCurrentChildSequence, 0, fCurrentChildSequence, 298 0, tmpCurrentChildSequence.length); 299 } 300 301 if (fIsResolveElement) { 303 if (event == XPointerPart.EVENT_ELEMENT_START) { 305 fCurrentChildSequence[fCurrentChildDepth] = fCurrentChildPosition; 306 fCurrentChildDepth++; 307 308 fCurrentChildPosition = 1; 310 311 if ((fCurrentChildDepth <= fFoundDepth) || (fFoundDepth == 0)) { 313 if (checkMatch()) { 314 fIsElementFound = true; 315 fFoundDepth = fCurrentChildDepth; 316 } else { 317 fIsElementFound = false; 318 fFoundDepth = 0; 319 } 320 } 321 322 } else if (event == XPointerPart.EVENT_ELEMENT_END) { 323 if (fCurrentChildDepth == fFoundDepth) { 324 fIsElementFound = true; 325 } else if (((fCurrentChildDepth < fFoundDepth) && (fFoundDepth != 0)) 326 || ((fCurrentChildDepth > fFoundDepth) && (fFoundDepth == 0))) { 328 fIsElementFound = false; 329 } 330 331 fCurrentChildSequence[fCurrentChildDepth] = 0; 333 334 fCurrentChildDepth--; 335 fCurrentChildPosition = fCurrentChildSequence[fCurrentChildDepth] + 1; 336 337 } else if (event == XPointerPart.EVENT_ELEMENT_EMPTY) { 338 339 fCurrentChildSequence[fCurrentChildDepth] = fCurrentChildPosition; 340 fCurrentChildPosition++; 341 342 if (checkMatch()) { 346 fIsElementFound = true; 347 fWasOnlyEmptyElementFound = true; 348 } else { 349 fIsElementFound = false; 350 } 351 353 } 354 } 355 356 return fIsElementFound; 357 } 358 359 366 protected boolean checkMatch() { 367 if (!fIsShortHand) { 370 if (fChildSequence.length <= fCurrentChildDepth + 1) { 373 374 for (int i = 0; i < fChildSequence.length; i++) { 375 if (fChildSequence[i] != fCurrentChildSequence[i]) { 376 return false; 377 } 378 } 379 } else { 380 return false; 381 } 382 } else { 383 if (fChildSequence.length <= fCurrentChildDepth + 1) { 387 388 for (int i = 0; i < fChildSequence.length; i++) { 389 if (fCurrentChildSequence.length < i + 2) { 391 return false; 392 } 393 394 if (fChildSequence[i] != fCurrentChildSequence[i + 1]) { 396 return false; 397 } 398 } 399 } else { 400 return false; 401 } 402 403 } 404 405 return true; 406 } 407 408 414 public boolean isFragmentResolved() throws XNIException { 415 return fIsFragmentResolved ; 418 } 419 420 427 public boolean isChildFragmentResolved() { 428 if (fIsShortHand && fShortHandPointer != null && fChildSequence.length <= 0) { 430 return fShortHandPointer.isChildFragmentResolved(); 431 } else { 432 return fWasOnlyEmptyElementFound ? !fWasOnlyEmptyElementFound 433 : (fIsFragmentResolved && (fCurrentChildDepth >= fFoundDepth)); 434 } 435 } 436 437 440 protected void reportError(String key, Object [] arguments) 441 throws XNIException { 442 445 throw new XNIException((fErrorReporter 446 .getMessageFormatter(XPointerMessageFormatter.XPOINTER_DOMAIN)) 447 .formatMessage(fErrorReporter.getLocale(), key, arguments)); 448 } 449 450 453 protected void initErrorReporter() { 454 if (fErrorReporter == null) { 455 fErrorReporter = new XMLErrorReporter(); 456 } 457 if (fErrorHandler == null) { 458 fErrorHandler = new XPointerErrorHandler(); 459 } 460 fErrorReporter.putMessageFormatter( 461 XPointerMessageFormatter.XPOINTER_DOMAIN, 462 new XPointerMessageFormatter()); 463 } 464 465 468 protected void init() { 469 fSchemeName = null; 470 fSchemeData = null; 471 fShortHandPointerName = null; 472 fIsResolveElement = false; 473 fIsElementFound = false; 474 fWasOnlyEmptyElementFound = false; 475 fFoundDepth = 0; 476 fCurrentChildPosition = 1; 477 fCurrentChildDepth = 0; 478 fIsFragmentResolved = false; 479 fShortHandPointer = null; 480 481 initErrorReporter(); 482 } 483 484 488 497 private final class Tokens { 498 499 504 private static final int XPTRTOKEN_ELEM_NCNAME = 0; 505 506 private static final int XPTRTOKEN_ELEM_CHILD = 1; 507 508 private final String [] fgTokenNames = { "XPTRTOKEN_ELEM_NCNAME", 510 "XPTRTOKEN_ELEM_CHILD" }; 511 512 private static final int INITIAL_TOKEN_COUNT = 1 << 8; 514 515 private int[] fTokens = new int[INITIAL_TOKEN_COUNT]; 516 517 private int fTokenCount = 0; 518 519 private int fCurrentTokenIndex; 521 522 private SymbolTable fSymbolTable; 523 524 private Hashtable fTokenNames = new Hashtable (); 525 526 531 private Tokens(SymbolTable symbolTable) { 532 fSymbolTable = symbolTable; 533 534 fTokenNames.put(new Integer (XPTRTOKEN_ELEM_NCNAME), 535 "XPTRTOKEN_ELEM_NCNAME"); 536 fTokenNames.put(new Integer (XPTRTOKEN_ELEM_CHILD), 537 "XPTRTOKEN_ELEM_CHILD"); 538 } 539 540 545 private String getTokenString(int token) { 546 return (String ) fTokenNames.get(new Integer (token)); 547 } 548 549 554 private Integer getToken(int token) { 555 return (Integer ) fTokenNames.get(new Integer (token)); 556 } 557 558 563 private void addToken(String tokenStr) { 564 Integer tokenInt = (Integer ) fTokenNames.get(tokenStr); 565 if (tokenInt == null) { 566 tokenInt = new Integer (fTokenNames.size()); 567 fTokenNames.put(tokenInt, tokenStr); 568 } 569 addToken(tokenInt.intValue()); 570 } 571 572 577 private void addToken(int token) { 578 try { 579 fTokens[fTokenCount] = token; 580 } catch (ArrayIndexOutOfBoundsException ex) { 581 int[] oldList = fTokens; 582 fTokens = new int[fTokenCount << 1]; 583 System.arraycopy(oldList, 0, fTokens, 0, fTokenCount); 584 fTokens[fTokenCount] = token; 585 } 586 fTokenCount++; 587 } 588 589 592 private void rewind() { 593 fCurrentTokenIndex = 0; 594 } 595 596 600 private boolean hasMore() { 601 return fCurrentTokenIndex < fTokenCount; 602 } 603 604 611 private int nextToken() throws XNIException { 612 if (fCurrentTokenIndex == fTokenCount) 613 reportError("XPointerElementSchemeProcessingError", null); 614 return fTokens[fCurrentTokenIndex++]; 615 } 616 617 624 private int peekToken() throws XNIException { 625 if (fCurrentTokenIndex == fTokenCount) 626 reportError("XPointerElementSchemeProcessingError", null); 627 return fTokens[fCurrentTokenIndex]; 628 } 629 630 638 private String nextTokenAsString() throws XNIException { 639 String s = getTokenString(nextToken()); 640 if (s == null) 641 reportError("XPointerElementSchemeProcessingError", null); 642 return s; 643 } 644 645 649 private int getTokenCount() { 650 return fTokenCount; 651 } 652 } 653 654 662 private class Scanner { 663 664 677 private static final byte CHARTYPE_INVALID = 0, CHARTYPE_OTHER = 1, CHARTYPE_MINUS = 2, CHARTYPE_PERIOD = 3, CHARTYPE_SLASH = 4, CHARTYPE_DIGIT = 5, CHARTYPE_LETTER = 6, CHARTYPE_UNDERSCORE = 7, CHARTYPE_NONASCII = 8; 687 private final byte[] fASCIICharMap = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 688 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 689 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 4, 5, 5, 5, 5, 5, 690 5, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 691 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 1, 1, 1, 692 7, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 693 6, 6, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1 }; 694 695 698 699 703 private SymbolTable fSymbolTable; 704 705 709 714 private Scanner(SymbolTable symbolTable) { 715 fSymbolTable = symbolTable; 717 718 } 720 724 private boolean scanExpr(SymbolTable symbolTable, Tokens tokens, 725 String data, int currentOffset, int endOffset) 726 throws XNIException { 727 728 int ch; 729 int nameOffset; 730 String nameHandle = null; 731 732 while (true) { 733 if (currentOffset == endOffset) { 734 break; 735 } 736 737 ch = data.charAt(currentOffset); 738 byte chartype = (ch >= 0x80) ? CHARTYPE_NONASCII 739 : fASCIICharMap[ch]; 740 741 746 switch (chartype) { 747 748 case CHARTYPE_SLASH: 749 if (++currentOffset == endOffset) { 751 return false; 752 } 753 754 addToken(tokens, Tokens.XPTRTOKEN_ELEM_CHILD); 755 ch = data.charAt(currentOffset); 756 757 int child = 0; 759 while (ch >= '0' && ch <= '9') { 760 child = (child * 10) + (ch - '0'); 761 if (++currentOffset == endOffset) { 762 break; 763 } 764 ch = data.charAt(currentOffset); 765 } 766 767 if (child == 0) { 769 reportError("InvalidChildSequenceCharacter", 770 new Object [] { new Character ((char) ch) }); 771 return false; 772 } 773 774 tokens.addToken(child); 775 776 break; 777 778 case CHARTYPE_DIGIT: 779 case CHARTYPE_LETTER: 780 case CHARTYPE_MINUS: 781 case CHARTYPE_NONASCII: 782 case CHARTYPE_OTHER: 783 case CHARTYPE_PERIOD: 784 case CHARTYPE_UNDERSCORE: 785 nameOffset = currentOffset; 787 currentOffset = scanNCName(data, endOffset, currentOffset); 788 789 if (currentOffset == nameOffset) { 790 reportError("InvalidNCNameInElementSchemeData", 792 new Object [] { data }); 793 return false; 794 } 795 796 if (currentOffset < endOffset) { 797 ch = data.charAt(currentOffset); 798 } else { 799 ch = -1; 800 } 801 802 nameHandle = symbolTable.addSymbol(data.substring( 803 nameOffset, currentOffset)); 804 addToken(tokens, Tokens.XPTRTOKEN_ELEM_NCNAME); 805 tokens.addToken(nameHandle); 806 807 break; 808 } 809 } 810 return true; 811 } 812 813 823 private int scanNCName(String data, int endOffset, int currentOffset) { 824 int ch = data.charAt(currentOffset); 825 if (ch >= 0x80) { 826 if (!XMLChar.isNameStart(ch)) { 827 return currentOffset; 828 } 829 } else { 830 byte chartype = fASCIICharMap[ch]; 831 if (chartype != CHARTYPE_LETTER 832 && chartype != CHARTYPE_UNDERSCORE) { 833 return currentOffset; 834 } 835 } 836 while (++currentOffset < endOffset) { 837 ch = data.charAt(currentOffset); 838 if (ch >= 0x80) { 839 if (!XMLChar.isName(ch)) { 840 break; 841 } 842 } else { 843 byte chartype = fASCIICharMap[ch]; 844 if (chartype != CHARTYPE_LETTER 845 && chartype != CHARTYPE_DIGIT 846 && chartype != CHARTYPE_PERIOD 847 && chartype != CHARTYPE_MINUS 848 && chartype != CHARTYPE_UNDERSCORE) { 849 break; 850 } 851 } 852 } 853 return currentOffset; 854 } 855 856 860 868 protected void addToken(Tokens tokens, int token) throws XNIException { 869 tokens.addToken(token); 870 } 872 } 874 } | Popular Tags |