1 19 20 21 package org.netbeans.modules.properties; 22 23 import java.beans.PropertyChangeEvent ; 24 import java.beans.PropertyChangeListener ; 25 import java.util.List ; 26 import java.util.ArrayList ; 27 import java.util.Collections ; 28 import java.util.Comparator ; 29 import java.util.Iterator ; 30 import java.util.Map ; 31 import java.util.TreeMap ; 32 import org.openide.loaders.MultiDataObject.Entry; 33 import org.openide.util.WeakListeners; 34 35 36 49 public class BundleStructure { 50 51 55 PropertiesDataObject obj; 56 57 65 private PropertiesFileEntry[] entries; 66 67 72 private List <String > keyList; 73 74 78 private KeyComparator comparator = new KeyComparator(); 79 80 85 private PropertyBundleSupport propBundleSupport 86 = new PropertyBundleSupport(this); 87 88 89 private PropertyChangeListener propListener; 90 91 98 public BundleStructure(PropertiesDataObject obj) { 99 this.obj = obj; 100 updateEntries(); 101 102 propListener = new PropertyChangeListener () { 104 public void propertyChange(PropertyChangeEvent evt) { 105 if (evt.getPropertyName().equals( 106 PropertiesDataObject.PROP_FILES)) { 107 updateEntries(); 108 propBundleSupport.fireBundleStructureChanged(); 109 } 110 } 111 }; 112 obj.addPropertyChangeListener( 113 WeakListeners.propertyChange(propListener, obj)); 114 } 115 116 117 125 public PropertiesFileEntry getNthEntry(int index) { 126 if (entries == null) { 127 notifyEntriesNotInitialized(); 128 } 129 if (index >= 0 && index < entries.length) { 130 return entries[index]; 131 } else { 132 return null; 133 } 134 } 135 136 147 public int getEntryIndexByFileName(String fileName) { 148 if (entries == null) { 149 notifyEntriesNotInitialized(); 150 } 151 for (int i = 0; i < getEntryCount(); i++) { 152 if (entries[i].getFile().getName().equals(fileName)) { 153 return i; 154 } 155 } 156 return -1; 157 } 158 159 170 public PropertiesFileEntry getEntryByFileName(String fileName) { 171 int index = getEntryIndexByFileName(fileName); 172 return ((index == -1) ? null : entries[index]); 173 } 174 175 182 public int getEntryCount() { 183 if (entries == null) { 184 notifyEntriesNotInitialized(); 185 } 186 return entries.length; 187 } 188 189 191 199 public String [] getKeys() { 200 if (keyList == null) { 201 notifyKeyListNotInitialized(); 202 } 203 return keyList.toArray(new String [0]); 204 } 205 206 215 public String keyAt(int keyIndex) { 216 if (keyList == null) { 217 notifyKeyListNotInitialized(); 218 } 219 if (keyIndex < 0 || keyIndex >= keyList.size()) { 220 return null; 221 } else { 222 return keyList.get(keyIndex); 223 } 224 } 225 226 235 public int getKeyIndexByName(String key) { 236 if (keyList == null) { 237 notifyKeyListNotInitialized(); 238 } 239 return keyList.indexOf(key); 240 } 241 242 246 public String findFreeKey(String keySpec) { 247 if (keyList == null) { 248 notifyKeyListNotInitialized(); 249 } 250 251 int n = 1; 252 String key = keySpec; 253 while (keyList.contains(key)) { 254 key = keySpec + "_" + n++; 255 } 256 return key; 257 } 258 259 267 public Element.ItemElem getItem(int entryIndex, int keyIndex) { 268 String key = keyAt(keyIndex); 269 return getItem(entryIndex, key); 270 } 271 272 290 public Element.ItemElem getItem(int entryIndex, String key) { 291 if (key == null) { 292 return null; 293 } 294 PropertiesFileEntry pfe = getNthEntry(entryIndex); 295 if (pfe == null) { 296 return null; 297 } 298 PropertiesStructure ps = pfe.getHandler().getStructure(); 299 if (ps != null) { 300 return ps.getItem(key); 301 } else { 302 return null; 303 } 304 } 305 306 314 public Element.ItemElem getItem(String localizationFile, String key) { 315 int score = 0; Element.ItemElem item = null; 317 for (int i=0; i < getEntryCount(); i++) { 318 PropertiesFileEntry pfe = getNthEntry(i); 319 if (pfe != null) { 320 String fName = pfe.getFile().getName(); 321 if (localizationFile.startsWith(fName) 322 && (item == null || fName.length() > score)) 323 { PropertiesStructure ps = pfe.getHandler().getStructure(); 326 if (ps != null) { 327 Element.ItemElem it = ps.getItem(key); 328 if (it != null) { 329 item = it; 330 score = fName.length(); 331 } 332 } 333 } 334 } 335 } 336 return item; 337 } 338 339 343 public String [] getAllData(String key) { 344 List <String > list = null; 345 for (int i=0; i < getEntryCount(); i++) { 346 PropertiesFileEntry pfe = getNthEntry(i); 347 if (pfe != null) { 348 PropertiesStructure ps = pfe.getHandler().getStructure(); 349 if (ps != null) { 350 Element.ItemElem item = ps.getItem(key); 351 if (item != null) { 352 String locale = Util.getLocaleSuffix(pfe); 353 if (list == null) { 354 list = new ArrayList <String >(); 355 } 356 list.add(locale); 357 list.add(item.getValue()); 358 list.add(item.getComment()); 359 } 360 } 361 } 362 } 363 return list != null ? list.toArray(new String [list.size()]) : null; 364 } 365 366 public void setAllData(String key, String [] data) { 367 boolean entryCreated = false; 369 for (int i=0; i < data.length; i+=3) { 370 String locale = data[i]; 371 PropertiesFileEntry localeFile = null; 372 for (int j=0; j < getEntryCount(); j++) { 373 PropertiesFileEntry pfe = getNthEntry(j); 374 if (pfe != null && Util.getLocaleSuffix(pfe).equals(locale)) { 375 localeFile = pfe; 376 break; 377 } 378 } 379 if (localeFile == null) { 380 Util.createLocaleFile(obj, locale.substring(1), false); 381 entryCreated = true; 382 } 383 } 384 if (entryCreated) 385 updateEntries(); 386 387 for (int i=0; i < data.length; i+=3) { 389 String locale = data[i]; 390 for (int j=0; j < getEntryCount(); j++) { 391 PropertiesFileEntry pfe = getNthEntry(j); 392 if (pfe != null && Util.getLocaleSuffix(pfe).equals(locale)) { 393 PropertiesStructure ps = pfe.getHandler().getStructure(); 394 if (ps != null) { 395 Element.ItemElem item = ps.getItem(key); 396 if (item != null) { 397 item.setValue(data[i+1]); 398 item.setComment(data[i+2]); 399 } 400 else { 401 ps.addItem(key, data[i+1], data[i+2]); 402 } 403 } 404 break; 405 } 406 } 407 } 408 409 if (getEntryCount() > data.length/3) { 411 for (int j=0; j < getEntryCount(); j++) { 412 PropertiesFileEntry pfe = getNthEntry(j); 413 PropertiesStructure ps = pfe.getHandler().getStructure(); 414 if (pfe == null || ps == null) continue; 415 416 boolean found = false; 417 for (int i=0; i < data.length; i+=3) { 418 String locale = data[i]; 419 if (Util.getLocaleSuffix(pfe).equals(locale)) { 420 found = true; 421 break; 422 } 423 } 424 if (!found) { 425 ps.deleteItem(key); 426 } 427 } 428 } 429 } 430 431 438 public int getKeyCount() { 439 if (keyList != null) { 440 return keyList.size(); 441 } else { 442 notifyKeyListNotInitialized(); 443 return 0; } 445 } 446 447 450 public void addItem(String localizationFile, 451 String key, String value, String comment, 452 boolean changeIfExists) 453 { 454 PropertiesStructure[] ps = getRelatedStructures(localizationFile); 455 boolean changed = false; 456 for (int i=0; i < ps.length; i++) { 457 Element.ItemElem item = ps[i].getItem(key); 458 if (item != null) { 459 if (changeIfExists && !changed) { 460 item.setValue(value); 461 item.setComment(comment); 462 changed = true; } 464 } 465 else { 466 ps[i].addItem(key, value, comment); 467 changed = true; } 469 } 470 } 471 472 475 public void removeItem(String key) { 476 for (int i=0; i < getEntryCount(); i++) { 477 PropertiesFileEntry pfe = getNthEntry(i); 478 if (pfe != null) { 479 PropertiesStructure ps = pfe.getHandler().getStructure(); 480 if (ps != null) { 481 ps.deleteItem(key); 482 } 483 } 484 } 485 } 486 487 495 public void sort(int index) { 496 if (index >= 0) { 497 comparator.setIndex(index); 498 } 499 Collections.sort(keyList, comparator); 500 propBundleSupport.fireBundleDataChanged(); 501 } 502 503 510 public int getSortIndex() { 511 return comparator.getIndex(); 512 } 513 514 520 public boolean getSortOrder() { 521 return comparator.isAscending(); 522 } 523 524 532 private void updateEntries() { 533 Map <String ,PropertiesFileEntry> tm = new TreeMap <String ,PropertiesFileEntry>( 534 PropertiesDataObject.getSecondaryFilesComparator()); 535 for (Entry entry : obj.secondaryEntries()) { 536 tm.put(entry.getFile().getName(), (PropertiesFileEntry) entry); 537 } 538 539 synchronized (this) { 540 int entriesCount = tm.size(); 542 entries = new PropertiesFileEntry[entriesCount + 1]; 543 entries[0] = (PropertiesFileEntry) obj.getPrimaryEntry(); 544 545 int index = 0; 546 for (Map.Entry <String ,PropertiesFileEntry> mapEntry : tm.entrySet()) { 547 entries[++index] = mapEntry.getValue(); 548 } 549 } 550 buildKeySet(); 551 } 552 553 558 private synchronized void buildKeySet() { 559 List <String > keyList = new ArrayList <String >() { 560 public boolean equals(Object obj) { 561 if (!(obj instanceof ArrayList )) { 562 return false; 563 } 564 ArrayList list2 = (ArrayList ) obj; 565 566 if (this.size() != list2.size()) { 567 return false; 568 } 569 for (int i = 0; i < this.size(); i++) { 570 if (!this.contains(list2.get(i)) 571 || !list2.contains(this.get(i))) { 572 return false; 573 } 574 } 575 return true; 576 } 577 }; 578 579 int entriesCount = getEntryCount(); 581 for (int index = 0; index < entriesCount; index++) { 582 PropertiesFileEntry entry = getNthEntry(index); 583 PropertiesStructure ps = entry.getHandler().getStructure(); 584 if (ps != null) { 585 for (Iterator <Element.ItemElem> it = ps.allItems(); it.hasNext(); ) { 586 Element.ItemElem item = it.next(); 587 if (item == null) { 588 continue; 589 } 590 String key = item.getKey(); 591 if (key != null && !(keyList.contains(key))) { 592 keyList.add(item.getKey()); 593 } 594 } 595 } 596 } 597 598 Collections.sort(keyList, comparator); 599 this.keyList = keyList; 600 } 601 602 608 private PropertiesStructure[] getRelatedStructures(String localizationFile) { 609 List <PropertiesFileEntry> list = null; 610 for (int i=0; i < getEntryCount(); i++) { 611 PropertiesFileEntry pfe = getNthEntry(i); 612 if (pfe != null) { 613 if (localizationFile.startsWith(pfe.getFile().getName()) 614 && pfe.getHandler().getStructure() != null) { 615 if (list == null) { 616 list = new ArrayList <PropertiesFileEntry>(4); 617 } 618 list.add(pfe); 619 } 620 } 621 } 622 if (list == null) { 623 return new PropertiesStructure[] {}; 624 } 625 Collections.sort(list, new Comparator <PropertiesFileEntry>() { 626 public int compare(PropertiesFileEntry pfe1, PropertiesFileEntry pfe2) { 627 return pfe2.getFile().getName().length() - pfe1.getFile().getName().length(); 628 } 629 }); 630 631 PropertiesStructure[] array = new PropertiesStructure[list.size()]; 632 for (int i=0, n=list.size(); i < n; i++) { 633 array[i] = list.get(i).getHandler().getStructure(); 634 } 635 return array; 636 } 637 638 boolean isReadOnly() { 639 boolean canWrite = false; 640 for (int i=0; i < getEntryCount(); i++) { 641 PropertiesFileEntry entry = getNthEntry(i); 642 canWrite |= entry.getFile().canWrite(); 643 } 644 return !canWrite; 645 } 646 647 656 public void addPropertyBundleListener(PropertyBundleListener l) { 657 propBundleSupport.addPropertyBundleListener(l); 658 } 659 660 669 public void removePropertyBundleListener(PropertyBundleListener l) { 670 propBundleSupport.removePropertyBundleListener(l); 671 } 672 673 681 void notifyItemChanged(PropertiesStructure struct, Element.ItemElem item) { 682 propBundleSupport.fireItemChanged( 683 struct.getParent().getEntry().getFile().getName(), 684 item.getKey() 685 ); 686 } 687 688 697 void notifyOneFileChanged(StructHandler handler) { 698 List oldKeyList = keyList; 702 703 buildKeySet(); 704 if (!keyList.equals(oldKeyList)) { 705 propBundleSupport.fireBundleDataChanged(); 706 } else { 707 propBundleSupport.fireFileChanged( 708 handler.getEntry().getFile().getName()); 709 } 710 } 711 712 723 void notifyOneFileChanged(StructHandler handler, 724 Map <String ,Element.ItemElem> itemsChanged, 725 Map <String ,Element.ItemElem> itemsAdded, 726 Map <String ,Element.ItemElem> itemsDeleted) { 727 buildKeySet(); 731 propBundleSupport.fireBundleDataChanged(); 732 } 733 734 741 private void notifyKeyListNotInitialized() { 742 throw new IllegalStateException ( 743 "Resource Bundles: KeyList not initialized"); } 745 746 753 private void notifyEntriesNotInitialized() { 754 throw new IllegalStateException ( 755 "Resource Bundles: Entries not initialized"); } 757 758 761 private final class KeyComparator implements Comparator <String > { 762 763 764 private int index; 765 766 767 private boolean ascending; 768 769 770 771 public KeyComparator() { 772 this.index = -1; 773 ascending = false; 774 } 775 776 777 783 public void setIndex(int index) { 784 if (index == -1) { 785 throw new IllegalArgumentException (); 786 } 787 if (this.index == index) { 789 if (ascending) { 790 ascending = false; 791 } else { 792 index = -1; 794 ascending = true; 795 } 796 } else { 797 ascending = true; 798 } 799 this.index = index; 800 } 801 802 807 public int getIndex() { 808 return index; 809 } 810 811 812 public boolean isAscending() { 813 return ascending; 814 } 815 816 819 public int compare(String o1, String o2) { 820 String str1; 821 String str2; 822 823 if (index < 0) { 825 Element.ItemElem item1 = getItem(0, o1); 826 Element.ItemElem item2 = getItem(0, o2); 827 if (item1 != null && item2 != null) { 828 int i1 = item1.getBounds().getBegin().getOffset(); 829 int i2 = item2.getBounds().getBegin().getOffset(); 830 return i1 - i2; 831 } else if (item1 != null) { 832 return -1; 833 } else if (item2 != null) { 834 return 1; 835 } else { 836 840 str1 = o1; 841 str2 = o2; 842 } 843 } 844 if (index == 0) { 846 str1 = o1; 847 str2 = o2; 848 } else { 849 Element.ItemElem item1 = getItem(index - 1, o1); 850 Element.ItemElem item2 = getItem(index - 1, o2); 851 if (item1 == null) { 852 if (item2 == null) { 853 return 0; 854 } else { 855 return ascending ? 1 : -1; 856 } 857 } else { 858 if (item2 == null) { 859 return ascending ? -1 : 1; 860 } 861 } 862 str1 = item1.getValue(); 863 str2 = item2.getValue(); 864 } 865 866 if (str1 == null) { 867 if (str2 == null) { 868 return 0; 869 } else { 870 return ascending ? 1 : -1; 871 } 872 } else if (str2 == null) { 873 return ascending ? -1 : 1; 874 } 875 int res = str1.compareToIgnoreCase(str2); 876 877 return ascending ? res : -res; 878 } 879 880 } 882 } 883 | Popular Tags |