1 10 11 package com.ibm.icu.text; 12 13 import com.ibm.icu.impl.ICUResourceBundle; 15 import com.ibm.icu.impl.LocaleUtility; 16 import com.ibm.icu.lang.UScript; 17 import com.ibm.icu.util.CaseInsensitiveString; 18 import com.ibm.icu.util.UResourceBundle; 19 20 import java.util.Enumeration ; 21 import java.util.Hashtable ; 22 import java.util.Locale ; 23 import java.util.MissingResourceException ; 24 import java.util.ResourceBundle ; 25 import java.util.Vector ; 26 27 class TransliteratorRegistry { 28 29 private static final char LOCALE_SEP = '_'; 31 32 private static final String NO_VARIANT = ""; private static final String ANY = "Any"; 35 36 47 private Hashtable registry; 48 49 60 private Hashtable specDAG; 61 62 65 private Vector availableIDs; 66 67 71 86 static class Spec { 87 88 private String top; private String spec; private String nextSpec; private String scriptName; private boolean isSpecLocale; private boolean isNextLocale; private ICUResourceBundle res; 95 96 public Spec(String theSpec) { 97 top = theSpec; 98 spec = null; 99 scriptName = null; 100 try{ 101 int script = UScript.getCodeFromName(top); 104 105 int[] s = UScript.getCode(top); 107 if (s != null) { 108 scriptName = UScript.getName(s[0]); 109 if (scriptName.equalsIgnoreCase(top)) { 111 scriptName = null; 112 } 113 } 114 115 isSpecLocale = false; 116 res = null; 117 if (script == UScript.INVALID_CODE) { 119 Locale toploc = LocaleUtility.getLocaleFromName(top); 120 res = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_TRANSLIT_BASE_NAME,toploc); 121 if (res!=null && LocaleUtility.isFallbackOf(res.getULocale().toString(), top)) { 123 isSpecLocale = true; 124 } 125 } 126 }catch(MissingResourceException e){ 127 scriptName = null; 128 } 129 reset(); 131 } 132 133 public boolean hasFallback() { 134 return nextSpec != null; 135 } 136 137 public void reset() { 138 if (spec != top) { spec = top; 140 isSpecLocale = (res != null); 141 setupNext(); 142 } 143 } 144 145 private void setupNext() { 146 isNextLocale = false; 147 if (isSpecLocale) { 148 nextSpec = spec; 149 int i = nextSpec.lastIndexOf(LOCALE_SEP); 150 if (i > 0) { 153 nextSpec = spec.substring(0, i); 154 isNextLocale = true; 155 } else { 156 nextSpec = scriptName; } 158 } else { 159 if (nextSpec != scriptName) { 161 nextSpec = scriptName; 162 } else { 163 nextSpec = null; 164 } 165 } 166 } 167 168 172 public String next() { 173 spec = nextSpec; 174 isSpecLocale = isNextLocale; 175 setupNext(); 176 return spec; 177 } 178 179 public String get() { 180 return spec; 181 } 182 183 public boolean isLocale() { 184 return isSpecLocale; 185 } 186 187 194 public ResourceBundle getBundle() { 195 if (res != null && 196 res.getULocale().toString().equals(spec)) { 197 return res; 198 } 199 return null; 200 } 201 202 public String getTop() { 203 return top; 204 } 205 } 206 207 211 static class ResourceEntry { 212 public String resource; 213 public String encoding; 214 public int direction; 215 public ResourceEntry(String n, String enc, int d) { 216 resource = n; 217 encoding = enc; 218 direction = d; 219 } 220 } 221 222 static class LocaleEntry { 224 public String rule; 225 public int direction; 226 public LocaleEntry(String r, int d) { 227 rule = r; 228 direction = d; 229 } 230 } 231 232 static class AliasEntry { 233 public String alias; 234 public AliasEntry(String a) { 235 alias = a; 236 } 237 } 238 239 static class CompoundRBTEntry { 240 private String ID; 241 private Vector idBlockVector; 242 private Vector dataVector; 243 private UnicodeSet compoundFilter; 244 245 public CompoundRBTEntry(String theID, Vector theIDBlockVector, 246 Vector theDataVector, 247 UnicodeSet theCompoundFilter) { 248 ID = theID; 249 idBlockVector = theIDBlockVector; 250 dataVector = theDataVector; 251 compoundFilter = theCompoundFilter; 252 } 253 254 public Transliterator getInstance() { 255 Vector transliterators = new Vector (); 256 int passNumber = 1; 257 258 int limit = Math.max(idBlockVector.size(), dataVector.size()); 259 for (int i = 0; i < limit; i++) { 260 if (i < idBlockVector.size()) { 261 String idBlock = (String )idBlockVector.get(i); 262 if (idBlock.length() > 0) 263 transliterators.add(Transliterator.getInstance(idBlock)); 264 } 265 if (i < dataVector.size()) { 266 RuleBasedTransliterator.Data data = (RuleBasedTransliterator.Data)dataVector.get(i); 267 transliterators.add(new RuleBasedTransliterator("%Pass" + passNumber++, data, null)); 268 } 269 } 270 271 Transliterator t = new CompoundTransliterator(transliterators, passNumber - 1); 272 t.setID(ID); 273 if (compoundFilter != null) { 274 t.setFilter(compoundFilter); 275 } 276 return t; 277 } 278 } 279 280 284 public TransliteratorRegistry() { 285 registry = new Hashtable (); 286 specDAG = new Hashtable (); 287 availableIDs = new Vector (); 288 } 289 290 300 public Transliterator get(String ID, 301 StringBuffer aliasReturn) { 302 Object [] entry = find(ID); 303 return (entry == null) ? null 304 : instantiateEntry(ID, entry, aliasReturn); 305 } 306 307 312 public void put(String ID, 313 Class transliteratorSubclass, 314 boolean visible) { 315 registerEntry(ID, transliteratorSubclass, visible); 316 } 317 318 323 public void put(String ID, 324 Transliterator.Factory factory, 325 boolean visible) { 326 registerEntry(ID, factory, visible); 327 } 328 329 334 public void put(String ID, 335 String resourceName, 336 String encoding, 337 int dir, 338 boolean visible) { 339 registerEntry(ID, new ResourceEntry(resourceName, encoding, dir), visible); 340 } 341 342 347 public void put(String ID, 348 String alias, 349 boolean visible) { 350 registerEntry(ID, new AliasEntry(alias), visible); 351 } 352 353 358 public void put(String ID, 359 Transliterator trans, 360 boolean visible) { 361 registerEntry(ID, trans, visible); 362 } 363 364 369 public void remove(String ID) { 370 String [] stv = TransliteratorIDParser.IDtoSTV(ID); 371 String id = TransliteratorIDParser.STVtoID(stv[0], stv[1], stv[2]); 373 registry.remove(new CaseInsensitiveString(id)); 374 removeSTV(stv[0], stv[1], stv[2]); 375 availableIDs.removeElement(new CaseInsensitiveString(id)); 376 } 377 378 382 386 private static class IDEnumeration implements Enumeration { 387 Enumeration en; 388 389 public IDEnumeration(Enumeration e) { 390 en = e; 391 } 392 393 public boolean hasMoreElements() { 394 return en != null && en.hasMoreElements(); 395 } 396 397 public Object nextElement() { 398 return ((CaseInsensitiveString) en.nextElement()).getString(); 399 } 400 } 401 402 408 public Enumeration getAvailableIDs() { 409 return new IDEnumeration(availableIDs.elements()); 412 } 413 414 419 public Enumeration getAvailableSources() { 420 return new IDEnumeration(specDAG.keys()); 421 } 422 423 429 public Enumeration getAvailableTargets(String source) { 430 CaseInsensitiveString cisrc = new CaseInsensitiveString(source); 431 Hashtable targets = (Hashtable ) specDAG.get(cisrc); 432 if (targets == null) { 433 return new IDEnumeration(null); 434 } 435 return new IDEnumeration(targets.keys()); 436 } 437 438 444 public Enumeration getAvailableVariants(String source, String target) { 445 CaseInsensitiveString cisrc = new CaseInsensitiveString(source); 446 CaseInsensitiveString citrg = new CaseInsensitiveString(target); 447 Hashtable targets = (Hashtable ) specDAG.get(cisrc); 448 if (targets == null) { 449 return new IDEnumeration(null); 450 } 451 Vector variants = (Vector ) targets.get(citrg); 452 if (variants == null) { 453 return new IDEnumeration(null); 454 } 455 return new IDEnumeration(variants.elements()); 456 } 457 458 462 465 private void registerEntry(String source, 466 String target, 467 String variant, 468 Object entry, 469 boolean visible) { 470 String s = source; 471 if (s.length() == 0) { 472 s = ANY; 473 } 474 String ID = TransliteratorIDParser.STVtoID(source, target, variant); 475 registerEntry(ID, s, target, variant, entry, visible); 476 } 477 478 481 private void registerEntry(String ID, 482 Object entry, 483 boolean visible) { 484 String [] stv = TransliteratorIDParser.IDtoSTV(ID); 485 String id = TransliteratorIDParser.STVtoID(stv[0], stv[1], stv[2]); 487 registerEntry(id, stv[0], stv[1], stv[2], entry, visible); 488 } 489 490 494 private void registerEntry(String ID, 495 String source, 496 String target, 497 String variant, 498 Object entry, 499 boolean visible) { 500 CaseInsensitiveString ciID = new CaseInsensitiveString(ID); 501 502 if (!(entry instanceof Object [])) { 504 entry = new Object [] { entry }; 505 } 506 507 registry.put(ciID, entry); 508 if (visible) { 509 registerSTV(source, target, variant); 510 if (!availableIDs.contains(ciID)) { 511 availableIDs.addElement(ciID); 512 } 513 } else { 514 removeSTV(source, target, variant); 515 availableIDs.removeElement(ciID); 516 } 517 } 518 519 525 private void registerSTV(String source, 526 String target, 527 String variant) { 528 CaseInsensitiveString cisrc = new CaseInsensitiveString(source); 531 CaseInsensitiveString citrg = new CaseInsensitiveString(target); 532 CaseInsensitiveString civar = new CaseInsensitiveString(variant); 533 Hashtable targets = (Hashtable ) specDAG.get(cisrc); 534 if (targets == null) { 535 targets = new Hashtable (); 536 specDAG.put(cisrc, targets); 537 } 538 Vector variants = (Vector ) targets.get(citrg); 539 if (variants == null) { 540 variants = new Vector (); 541 targets.put(citrg, variants); 542 } 543 if (!variants.contains(civar)) { 547 if (variant.length() > 0) { 548 variants.addElement(civar); 549 } else { 550 variants.insertElementAt(civar, 0); 551 } 552 } 553 } 554 555 558 private void removeSTV(String source, 559 String target, 560 String variant) { 561 CaseInsensitiveString cisrc = new CaseInsensitiveString(source); 564 CaseInsensitiveString citrg = new CaseInsensitiveString(target); 565 CaseInsensitiveString civar = new CaseInsensitiveString(variant); 566 Hashtable targets = (Hashtable ) specDAG.get(cisrc); 567 if (targets == null) { 568 return; } 570 Vector variants = (Vector ) targets.get(citrg); 571 if (variants == null) { 572 return; } 574 variants.removeElement(civar); 575 if (variants.size() == 0) { 576 targets.remove(citrg); if (targets.size() == 0) { 578 specDAG.remove(cisrc); } 580 } 581 } 582 583 private static final boolean DEBUG = false; 584 585 589 private Object [] findInDynamicStore(Spec src, 590 Spec trg, 591 String variant) { 592 String ID = TransliteratorIDParser.STVtoID(src.get(), trg.get(), variant); 593 if (DEBUG) { 594 System.out.println("TransliteratorRegistry.findInDynamicStore:" + 595 ID); 596 } 597 return (Object []) registry.get(new CaseInsensitiveString(ID)); 598 } 599 600 609 private Object [] findInStaticStore(Spec src, 610 Spec trg, 611 String variant) { 612 if (DEBUG) { 613 String ID = TransliteratorIDParser.STVtoID(src.get(), trg.get(), variant); 614 System.out.println("TransliteratorRegistry.findInStaticStore:" + 615 ID); 616 } 617 Object [] entry = null; 618 if (src.isLocale()) { 619 entry = findInBundle(src, trg, variant, Transliterator.FORWARD); 620 } else if (trg.isLocale()) { 621 entry = findInBundle(trg, src, variant, Transliterator.REVERSE); 622 } 623 624 if (entry != null) { 627 registerEntry(src.getTop(), trg.getTop(), variant, entry, false); 628 } 629 630 return entry; 631 } 632 633 643 private Object [] findInBundle(Spec specToOpen, 644 Spec specToFind, 645 String variant, 646 int direction) { 647 ResourceBundle res = specToOpen.getBundle(); 649 650 if (res == null) { 651 return null; 654 } 655 656 for (int pass=0; pass<2; ++pass) { 657 StringBuffer tag = new StringBuffer (); 658 if (pass == 0) { 663 tag.append(direction == Transliterator.FORWARD ? 664 "TransliterateTo" : "TransliterateFrom"); 665 } else { 666 tag.append("Transliterate"); 667 } 668 tag.append(specToFind.get().toUpperCase()); 669 670 try { 671 String [] subres = res.getStringArray(tag.toString()); 675 676 int i = 0; 679 if (variant.length() != 0) { 680 for (i=0; i<subres.length; i+= 2) { 681 if (subres[i].equalsIgnoreCase(variant)) { 682 break; 683 } 684 } 685 } 686 687 if (i < subres.length) { 688 693 int dir = (pass == 0) ? Transliterator.FORWARD : direction; 700 return new Object [] { new LocaleEntry(subres[i+1], dir) }; 701 } 702 703 } catch (MissingResourceException e) { 704 if (DEBUG) System.out.println("missing resource: " + e); 705 } 706 } 707 708 return null; 711 } 712 713 716 private Object [] find(String ID) { 717 String [] stv = TransliteratorIDParser.IDtoSTV(ID); 718 return find(stv[0], stv[1], stv[2]); 719 } 720 721 742 private Object [] find(String source, 743 String target, 744 String variant) { 745 746 Spec src = new Spec(source); 747 Spec trg = new Spec(target); 748 Object [] entry = null; 749 750 if (variant.length() != 0) { 751 752 entry = findInDynamicStore(src, trg, variant); 754 if (entry != null) { 755 return entry; 756 } 757 758 entry = findInStaticStore(src, trg, variant); 760 if (entry != null) { 761 return entry; 762 } 763 } 764 765 for (;;) { 766 src.reset(); 767 for (;;) { 768 entry = findInDynamicStore(src, trg, NO_VARIANT); 770 if (entry != null) { 771 return entry; 772 } 773 774 entry = findInStaticStore(src, trg, NO_VARIANT); 776 if (entry != null) { 777 return entry; 778 } 779 if (!src.hasFallback()) { 780 break; 781 } 782 src.next(); 783 } 784 if (!trg.hasFallback()) { 785 break; 786 } 787 trg.next(); 788 } 789 790 return null; 791 } 792 793 805 private Transliterator instantiateEntry(String ID, 806 Object [] entryWrapper, 807 StringBuffer aliasReturn) { 808 816 for (;;) { 817 Object entry = entryWrapper[0]; 818 819 if (entry instanceof RuleBasedTransliterator.Data) { 820 RuleBasedTransliterator.Data data = (RuleBasedTransliterator.Data) entry; 821 return new RuleBasedTransliterator(ID, data, null); 822 } else if (entry instanceof Class ) { 823 try { 824 return (Transliterator) ((Class ) entry).newInstance(); 825 } catch (InstantiationException e) { 826 } catch (IllegalAccessException e2) {} 827 return null; 828 } else if (entry instanceof AliasEntry) { 829 aliasReturn.append(((AliasEntry) entry).alias); 830 return null; 831 } else if (entry instanceof Transliterator.Factory) { 832 return ((Transliterator.Factory) entry).getInstance(ID); 833 } else if (entry instanceof CompoundRBTEntry) { 834 return ((CompoundRBTEntry) entry).getInstance(); 835 } else if (entry instanceof Transliterator) { 836 return (Transliterator) entry; 837 } 838 839 845 TransliteratorParser parser = new TransliteratorParser(); 846 847 try { 848 849 ResourceEntry re = (ResourceEntry) entry; 850 parser.parse(re.resource, re.direction); 851 852 } catch (ClassCastException e) { 853 LocaleEntry le = (LocaleEntry) entry; 856 parser.parse(le.rule, le.direction); 857 } 858 859 if (parser.idBlockVector.size() == 0 && parser.dataVector.size() == 0) { 865 entryWrapper[0] = new AliasEntry(NullTransliterator._ID); 868 } 869 else if (parser.idBlockVector.size() == 0 && parser.dataVector.size() == 1) { 870 entryWrapper[0] = parser.dataVector.get(0); 873 } 874 else if (parser.idBlockVector.size() == 1 && parser.dataVector.size() == 0) { 875 if (parser.compoundFilter != null) 880 entryWrapper[0] = new AliasEntry(parser.compoundFilter.toPattern(false) + ";" 881 + (String )parser.idBlockVector.get(0)); 882 else 883 entryWrapper[0] = new AliasEntry((String )parser.idBlockVector.get(0)); 884 } 885 else { 886 entryWrapper[0] = new CompoundRBTEntry(ID, parser.idBlockVector, parser.dataVector, 887 parser.compoundFilter); 888 } 889 } 890 } 891 } 892 893 | Popular Tags |