1 package com.icl.saxon.om; 2 import com.icl.saxon.style.StandardNames; 3 import javax.xml.transform.TransformerException ; 4 import java.util.StringTokenizer ; 5 import java.util.Vector ; 6 7 22 23 public class NamePool { 24 25 48 49 52 private static NamePool defaultNamePool = new NamePool(); 53 static { 54 defaultNamePool.loadStandardNames(); 55 } 56 57 private StandardNames standardNames = null; 58 59 62 63 public static NamePool getDefaultNamePool() { 64 return defaultNamePool; 65 } 66 67 68 private class NameEntry { 69 String localName; 70 short uriCode; 71 NameEntry nextEntry; 73 public NameEntry(short uriCode, String localName) { 74 this.uriCode = uriCode; 75 this.localName = localName; 76 this.nextEntry = null; 77 } 78 79 } 80 81 NameEntry[] hashslots = new NameEntry[1024]; 82 83 String [] prefixes = new String [100]; 84 short prefixesUsed = 0; 85 String [] uris = new String [100]; 86 String [] prefixesForUri = new String [100]; 87 short urisUsed = 0; 88 Vector signatures = new Vector (); boolean sealed = false; 91 94 public NamePool() { 95 96 prefixes[Namespace.NULL_CODE] = ""; 97 uris[Namespace.NULL_CODE] = Namespace.NULL; 98 prefixesForUri[Namespace.NULL_CODE] = ""; 99 100 prefixes[Namespace.XML_CODE] = "xml"; 101 uris[Namespace.XML_CODE] = Namespace.XML; 102 prefixesForUri[Namespace.XML_CODE] = "xml "; 103 104 prefixes[Namespace.XSLT_CODE] = "xsl"; 105 uris[Namespace.XSLT_CODE] = Namespace.XSLT; 106 prefixesForUri[Namespace.XSLT_CODE] = "xsl "; 107 108 prefixes[Namespace.SAXON_CODE] = "saxon"; 109 uris[Namespace.SAXON_CODE] = Namespace.SAXON; 110 prefixesForUri[Namespace.SAXON_CODE] = "saxon "; 111 112 prefixes[Namespace.EXSLT_FUNCTIONS_CODE] = "func"; 113 uris[Namespace.EXSLT_FUNCTIONS_CODE] = Namespace.EXSLT_FUNCTIONS; 114 prefixesForUri[Namespace.EXSLT_FUNCTIONS_CODE] = "func "; 115 116 prefixesUsed = 5; 117 urisUsed = 5; 118 119 } 120 121 124 125 public synchronized void loadStandardNames() { 126 if (standardNames==null) { 127 standardNames = new StandardNames(this); 128 standardNames.allocateNames(); 129 } 130 } 131 132 135 136 public StandardNames getStandardNames() { 137 return standardNames; 138 } 139 140 144 145 public synchronized void setStylesheetSignature(Object sig) { 146 signatures.addElement(new Integer (sig.hashCode())); 148 } 150 151 155 156 public boolean hasSignature(Object sig) { 157 160 return signatures.contains(new Integer (sig.hashCode())); 161 } 162 163 169 170 public synchronized void importPool(NamePool other) throws TransformerException { 171 172 174 if (signatures.size()>0) { 175 throw new TransformerException ("Cannot merge names into a non-empty namepool"); 176 } 177 178 for (int s=0; s<other.signatures.size(); s++) { 179 signatures.addElement(other.signatures.elementAt(s)); 180 } 181 182 for (int i=0; i<1024; i++) { 183 NameEntry entry = other.hashslots[i]; 184 NameEntry prev = null; 185 while (entry != null) { 186 NameEntry copy = new NameEntry(entry.uriCode, entry.localName); 187 if (prev==null) { 188 hashslots[i] = copy; 189 } else { 190 prev.nextEntry = copy; 191 } 192 prev = copy; 193 entry = entry.nextEntry; 194 } 195 } 196 197 this.prefixesUsed = other.prefixesUsed; 198 this.urisUsed = other.urisUsed; 199 if (prefixesUsed > 60) { 200 this.prefixes = new String [prefixesUsed * 2]; 201 } 202 if (urisUsed > 60) { 203 this.uris = new String [urisUsed * 2]; 204 this.prefixesForUri = new String [urisUsed * 2]; 205 } 206 System.arraycopy(other.prefixes, 0, this.prefixes, 0, prefixesUsed); 207 System.arraycopy(other.uris, 0, this.uris, 0, urisUsed); 208 System.arraycopy(other.prefixesForUri, 0, this.prefixesForUri, 0, urisUsed); 209 210 other.sealed = true; 211 } 212 213 216 217 public boolean isSealed() { 218 return sealed; 219 } 220 221 225 226 private NameEntry getNameEntry(int nameCode) { 227 int hash = nameCode & 0x3ff; 228 int depth = (nameCode >> 10) & 0x3ff; 229 NameEntry entry = hashslots[hash]; 230 231 for (int i=0; i<depth; i++) { 232 if (entry==null) return null; 233 entry = entry.nextEntry; 234 } 235 return entry; 236 } 237 238 242 243 public synchronized int allocateNamespaceCode(String prefix, String uri) { 244 246 int prefixCode = allocateCodeForPrefix(prefix); 247 int uriCode = allocateCodeForURI(uri); 248 249 if (prefixCode!=0) { 250 String key = prefix + " "; 252 if (prefixesForUri[uriCode].indexOf(key) < 0) { 253 prefixesForUri[uriCode] += key; 254 } 255 } 256 257 return (prefixCode<<16) + uriCode; 258 } 259 260 264 265 public int getNamespaceCode(String prefix, String uri) { 266 int prefixCode = getCodeForPrefix(prefix); 268 if (prefixCode<0) return -1; 269 int uriCode = getCodeForURI(uri); 270 if (uriCode<0) return -1; 271 272 if (prefixCode!=0) { 273 String key = prefix + " "; 275 if (prefixesForUri[uriCode].indexOf(key) < 0) { 276 return -1; 277 } 278 } 279 280 return (prefixCode<<16) + uriCode; 281 } 282 283 287 288 public synchronized short allocateCodeForURI(String uri) { 289 for (short j=0; j<urisUsed; j++) { 291 if (uris[j].equals(uri)) { 292 return j; 293 } 294 } 295 if (sealed) { 296 throw new IllegalArgumentException ("Namepool has been sealed"); 297 } 298 if (urisUsed >= uris.length) { 299 if (urisUsed>32000) { 300 throw new IllegalArgumentException ("Too many namespace URIs"); 301 } 302 String [] p = new String [urisUsed*2]; 303 String [] u = new String [urisUsed*2]; 304 System.arraycopy(prefixesForUri, 0, p, 0, urisUsed); 305 System.arraycopy(uris, 0, u, 0, urisUsed); 306 prefixesForUri = p; 307 uris = u; 308 } 309 uris[urisUsed] = uri; 310 prefixesForUri[urisUsed] = ""; 311 return urisUsed++; 312 } 313 314 315 316 320 321 public short getCodeForURI(String uri) { 322 for (short j=0; j<urisUsed; j++) { 323 if (uris[j].equals(uri)) { 324 return j; 325 } 326 } 327 return -1; 328 } 329 330 333 334 public synchronized short allocateCodeForPrefix(String prefix) { 335 for (short i=0; i<prefixesUsed; i++) { 336 if (prefixes[i].equals(prefix)) { 337 return i; 338 } 339 } 340 if (sealed) { 341 throw new IllegalArgumentException ("Namepool has been sealed"); 342 } 343 if (prefixesUsed >= prefixes.length) { 344 if (prefixesUsed>32000) { 345 throw new IllegalArgumentException ("Too many namespace prefixes"); 346 } 347 String [] p = new String [prefixesUsed*2]; 348 System.arraycopy(prefixes, 0, p, 0, prefixesUsed); 349 prefixes = p; 350 } 351 prefixes[prefixesUsed] = prefix; 352 return prefixesUsed++; 353 } 354 355 356 360 361 public short getCodeForPrefix(String prefix) { 362 for (short i=0; i<prefixesUsed; i++) { 363 if (prefixes[i].equals(prefix)) { 364 return i; 365 } 366 } 367 return -1; 368 } 369 370 374 375 public int getPrefixIndex(short uriCode, String prefix) { 376 377 if (prefix.equals("")) return 0; 379 if (prefixesForUri[uriCode].equals(prefix+" ")) return 1; 380 381 int i = 1; 383 StringTokenizer tok = new StringTokenizer (prefixesForUri[uriCode]); 384 while (tok.hasMoreElements()) { 385 if (prefix.equals(tok.nextElement())) { 386 return i; 387 } 388 if (i++==255) { 389 throw new IllegalArgumentException ("Too many prefixes for one namespace URI"); 390 } 391 } 392 return -1; 393 } 394 395 399 400 public String getPrefixWithIndex(short uriCode, int index) { 401 if (index==0) return ""; 402 StringTokenizer tok = new StringTokenizer (prefixesForUri[uriCode]); 403 int i=1; 404 while (tok.hasMoreElements()) { 405 String prefix = (String )tok.nextElement(); 406 if (i++ == index) { 407 return prefix; 408 } 409 } 410 return null; 411 } 412 413 421 422 public synchronized int allocate(String prefix, String uri, String localName) { 423 short uriCode = allocateCodeForURI(uri); 424 return allocate(prefix, uriCode, localName); 425 } 426 427 434 435 public synchronized int allocate(String prefix, short uriCode, String localName) { 436 int hash = (localName.hashCode() & 0x7fffffff) % 1023; 438 int depth = 0; 439 int prefixIndex = getPrefixIndex(uriCode, prefix); 440 441 if (prefixIndex<0) { 442 prefixesForUri[uriCode] += (prefix + " "); 443 prefixIndex = getPrefixIndex(uriCode, prefix); 444 } 445 NameEntry entry = null; 446 447 if (hashslots[hash]==null) { 448 if (sealed) { 449 throw new IllegalArgumentException ("Namepool has been sealed"); 450 } 451 entry = new NameEntry(uriCode, localName); 452 hashslots[hash] = entry; 453 } else { 454 entry = hashslots[hash]; 455 while (true) { 456 boolean sameLocalName = (entry.localName.equals(localName)); 457 boolean sameURI = (entry.uriCode==uriCode); 458 459 if (sameLocalName && sameURI) { 460 break; 462 } else { 463 NameEntry next = entry.nextEntry; 464 depth++; 465 if (depth >= 1024) { 466 throw new java.lang.IllegalArgumentException ("Saxon name pool is full"); 467 } 468 if (next==null) { 469 if (sealed) { 470 throw new IllegalArgumentException ("Namepool has been sealed"); 471 } 472 NameEntry newentry = new NameEntry(uriCode, localName); 473 entry.nextEntry = newentry; 474 break; 475 } else { 476 entry = next; 477 } 478 } 479 } 480 } 481 return ((prefixIndex<<20) + (depth<<10) + hash); 483 } 484 485 488 489 public synchronized int allocateNamespaceCode(int namecode) { 490 String prefix = getPrefix(namecode); 491 int uriCode = getURICode(namecode); 492 int prefixCode = allocateCodeForPrefix(prefix); 493 return (prefixCode<<16) + uriCode; 494 } 495 496 497 500 501 public int getNamespaceCode(int namecode) { 502 String prefix = getPrefix(namecode); 503 int uriCode = getURICode(namecode); 504 int prefixCode = getCodeForPrefix(prefix); 505 return (prefixCode<<16) + uriCode; 506 } 507 508 511 512 public String getURI(int nameCode) { 513 NameEntry entry = getNameEntry(nameCode); 514 if (entry==null) { 515 unknownNameCode(nameCode); 516 } 517 return uris[entry.uriCode]; 518 } 519 520 523 524 public short getURICode(int nameCode) { 525 NameEntry entry = getNameEntry(nameCode); 526 if (entry==null) { 527 unknownNameCode(nameCode); 528 } 529 return entry.uriCode; 530 } 531 532 535 536 public String getLocalName(int nameCode) { 537 NameEntry entry = getNameEntry(nameCode); 538 if (entry==null) { 539 unknownNameCode(nameCode); 540 } 541 return entry.localName; 542 } 543 544 547 548 public String getPrefix(int nameCode) { 549 short uriCode = getURICode(nameCode); 550 int prefixIndex = (nameCode >> 20) & 0xff; 551 return getPrefixWithIndex(uriCode, prefixIndex); 552 } 553 554 557 558 public String getDisplayName(int nameCode) { 559 NameEntry entry = getNameEntry(nameCode); 560 if (entry==null) { 561 unknownNameCode(nameCode); 562 } 563 int prefixIndex = (nameCode >> 20) & 0xff; 564 if (prefixIndex==0) return entry.localName; 565 return getPrefixWithIndex(entry.uriCode, prefixIndex) + ':' + entry.localName; 566 } 567 568 573 574 private void unknownNameCode(int nameCode) { 575 System.err.println("Unknown name code " + nameCode); 576 diagnosticDump(); 577 (new IllegalArgumentException ("Unknown name")).printStackTrace(); 578 throw new IllegalArgumentException ("Unknown name code " + nameCode); 579 } 580 581 586 587 public int getFingerprint(int nameCode) { 588 return nameCode & 0xfffff; } 590 591 598 599 public int getFingerprint(String uri, String localName) { 600 602 short uriCode = -1; 603 for (short j=0; j<urisUsed; j++) { 604 if (uris[j].equals(uri)) { 605 uriCode = j; 606 break; 607 } 608 } 609 610 if (uriCode==-1) return -1; 611 612 int hash = (localName.hashCode() & 0x7fffffff) % 1023; 613 int depth = 0; 614 615 NameEntry entry = null; 616 617 if (hashslots[hash]==null) { 618 return -1; 619 } else { 620 entry = hashslots[hash]; 621 while (true) { 622 boolean sameLocalName = (entry.localName.equals(localName)); 623 boolean sameURI = (entry.uriCode==uriCode); 624 625 if (sameLocalName && sameURI) { 626 break; 627 } else { 628 NameEntry next = entry.nextEntry; 629 depth++; 630 if (next==null) { 631 return -1; 632 } else { 633 entry = next; 634 } 635 } 636 } 637 } 638 return (depth<<10) + hash; 639 } 640 641 644 645 public String getURIFromNamespaceCode(int code) { 646 return uris[code&0xffff]; 647 } 648 649 652 653 public String getURIFromURICode(short code) { 654 return uris[code]; 655 } 656 657 660 661 public String getPrefixFromNamespaceCode(int code) { 662 return prefixes[code>>16]; 664 } 665 666 667 668 671 672 public synchronized void diagnosticDump() { 673 System.err.println("Contents of NamePool " + this); 674 for (int i=0; i<1024; i++) { 675 NameEntry entry = hashslots[i]; 676 int depth = 0; 677 while (entry != null) { 678 System.err.println("Fingerprint " + depth + "/" + i); 679 System.err.println(" local name = " + entry.localName + 680 " uri code = " + entry.uriCode); 681 entry = entry.nextEntry; 682 depth++; 683 } 684 } 685 686 for (int p=0; p<prefixesUsed; p++) { 687 System.err.println("Prefix " + p + " = " + prefixes[p]); 688 } 689 for (int u=0; u<urisUsed; u++) { 690 System.err.println("URI " + u + " = " + uris[u]); 691 System.err.println("Prefixes for URI " + u + " = " + prefixesForUri[u]); 692 } 693 } 694 695 701 702 public void generateJavaConstants() { 703 System.out.println("// Declarations generated from NamePool"); 704 for (int i=0; i<1024; i++) { 705 NameEntry entry = hashslots[i]; 706 int depth = 0; 707 while (entry != null) { 708 int fingerprint = (depth<<10) + i; 709 String prefix=""; 710 if (entry.uriCode==Namespace.NULL_CODE) prefix=""; 711 else if (entry.uriCode==Namespace.XSLT_CODE) prefix="XSL_"; 712 else if (entry.uriCode==Namespace.XML_CODE) prefix="XML_"; 713 else if (entry.uriCode==Namespace.SAXON_CODE) prefix="SAXON_"; 714 String localname = entry.localName.toUpperCase(); 715 while (true) { 716 int h = localname.indexOf('-'); 717 if (h<0) break; 718 localname = localname.substring(0, h) + '_' + localname.substring(h+1); 719 } 720 721 System.out.println("public final static int " + 722 prefix + localname + " = " + fingerprint + ";"); 723 entry = entry.nextEntry; 724 depth++; 725 } 726 } 727 } 728 729 730 731 } 732 733 | Popular Tags |