1 7 8 package java.text; 9 10 import java.util.*; 11 import java.text.AttributedCharacterIterator.Attribute; 12 13 23 24 public class AttributedString { 25 26 private static final int ARRAY_SIZE_INCREMENT = 10; 29 30 String text; 32 33 int runArraySize; int runCount; int runStarts[]; Vector runAttributes[]; Vector runAttributeValues[]; 41 49 AttributedString(AttributedCharacterIterator [] iterators) { 50 if (iterators == null) { 51 throw new NullPointerException ("Iterators must not be null"); 52 } 53 if (iterators.length == 0) { 54 text = ""; 55 } 56 else { 57 StringBuffer buffer = new StringBuffer (); 59 for (int counter = 0; counter < iterators.length; counter++) { 60 appendContents(buffer, iterators[counter]); 61 } 62 63 text = buffer.toString(); 64 65 if (text.length() > 0) { 66 int offset = 0; 69 Map last = null; 70 71 for (int counter = 0; counter < iterators.length; counter++) { 72 AttributedCharacterIterator iterator = iterators[counter]; 73 int start = iterator.getBeginIndex(); 74 int end = iterator.getEndIndex(); 75 int index = start; 76 77 while (index < end) { 78 iterator.setIndex(index); 79 80 Map attrs = iterator.getAttributes(); 81 82 if (mapsDiffer(last, attrs)) { 83 setAttributes(attrs, index - start + offset); 84 } 85 last = attrs; 86 index = iterator.getRunLimit(); 87 } 88 offset += (end - start); 89 } 90 } 91 } 92 } 93 94 98 public AttributedString(String text) { 99 if (text == null) { 100 throw new NullPointerException (); 101 } 102 this.text = text; 103 } 104 105 113 public AttributedString(String text, 114 Map<? extends Attribute, ?> attributes) 115 { 116 if (text == null || attributes == null) { 117 throw new NullPointerException (); 118 } 119 this.text = text; 120 121 if (text.length() == 0) { 122 if (attributes.isEmpty()) 123 return; 124 throw new IllegalArgumentException ("Can't add attribute to 0-length text"); 125 } 126 127 int attributeCount = attributes.size(); 128 if (attributeCount > 0) { 129 createRunAttributeDataVectors(); 130 Vector newRunAttributes = new Vector(attributeCount); 131 Vector newRunAttributeValues = new Vector(attributeCount); 132 runAttributes[0] = newRunAttributes; 133 runAttributeValues[0] = newRunAttributeValues; 134 Iterator iterator = attributes.entrySet().iterator(); 135 while (iterator.hasNext()) { 136 Map.Entry entry = (Map.Entry) iterator.next(); 137 newRunAttributes.addElement(entry.getKey()); 138 newRunAttributeValues.addElement(entry.getValue()); 139 } 140 } 141 } 142 143 148 public AttributedString(AttributedCharacterIterator text) { 149 this(text, text.getBeginIndex(), text.getEndIndex(), null); 153 } 154 155 171 public AttributedString(AttributedCharacterIterator text, 172 int beginIndex, 173 int endIndex) { 174 this(text, beginIndex, endIndex, null); 175 } 176 177 198 public AttributedString(AttributedCharacterIterator text, 199 int beginIndex, 200 int endIndex, 201 Attribute[] attributes) { 202 if (text == null) { 203 throw new NullPointerException (); 204 } 205 206 int textBeginIndex = text.getBeginIndex(); 208 int textEndIndex = text.getEndIndex(); 209 if (beginIndex < textBeginIndex || endIndex > textEndIndex || beginIndex > endIndex) 210 throw new IllegalArgumentException ("Invalid substring range"); 211 212 StringBuffer textBuffer = new StringBuffer (); 214 text.setIndex(beginIndex); 215 for (char c = text.current(); text.getIndex() < endIndex; c = text.next()) 216 textBuffer.append(c); 217 this.text = textBuffer.toString(); 218 219 if (beginIndex == endIndex) 220 return; 221 222 HashSet keys = new HashSet(); 224 if (attributes == null) { 225 keys.addAll(text.getAllAttributeKeys()); 226 } else { 227 for (int i = 0; i < attributes.length; i++) 228 keys.add(attributes[i]); 229 keys.retainAll(text.getAllAttributeKeys()); 230 } 231 if (keys.isEmpty()) 232 return; 233 234 Iterator itr = keys.iterator(); 238 while (itr.hasNext()) { 239 Attribute attributeKey = (Attribute)itr.next(); 240 text.setIndex(textBeginIndex); 241 while (text.getIndex() < endIndex) { 242 int start = text.getRunStart(attributeKey); 243 int limit = text.getRunLimit(attributeKey); 244 Object value = text.getAttribute(attributeKey); 245 246 if (value != null) { 247 if (value instanceof Annotation ) { 248 if (start >= beginIndex && limit <= endIndex) { 249 addAttribute(attributeKey, value, start - beginIndex, limit - beginIndex); 250 } else { 251 if (limit > endIndex) 252 break; 253 } 254 } else { 255 if (start >= endIndex) 258 break; 259 if (limit > beginIndex) { 260 if (start < beginIndex) 262 start = beginIndex; 263 if (limit > endIndex) 264 limit = endIndex; 265 if (start != limit) { 266 addAttribute(attributeKey, value, start - beginIndex, limit - beginIndex); 267 } 268 } 269 } 270 } 271 text.setIndex(limit); 272 } 273 } 274 } 275 276 283 public void addAttribute(Attribute attribute, Object value) { 284 285 if (attribute == null) { 286 throw new NullPointerException (); 287 } 288 289 int len = length(); 290 if (len == 0) { 291 throw new IllegalArgumentException ("Can't add attribute to 0-length text"); 292 } 293 294 addAttributeImpl(attribute, value, 0, len); 295 } 296 297 307 public void addAttribute(Attribute attribute, Object value, 308 int beginIndex, int endIndex) { 309 310 if (attribute == null) { 311 throw new NullPointerException (); 312 } 313 314 if (beginIndex < 0 || endIndex > length() || beginIndex >= endIndex) { 315 throw new IllegalArgumentException ("Invalid substring range"); 316 } 317 318 addAttributeImpl(attribute, value, beginIndex, endIndex); 319 } 320 321 333 public void addAttributes(Map<? extends Attribute, ?> attributes, 334 int beginIndex, int endIndex) 335 { 336 if (attributes == null) { 337 throw new NullPointerException (); 338 } 339 340 if (beginIndex < 0 || endIndex > length() || beginIndex > endIndex) { 341 throw new IllegalArgumentException ("Invalid substring range"); 342 } 343 if (beginIndex == endIndex) { 344 if (attributes.isEmpty()) 345 return; 346 throw new IllegalArgumentException ("Can't add attribute to 0-length text"); 347 } 348 349 if (runCount == 0) { 351 createRunAttributeDataVectors(); 352 } 353 354 int beginRunIndex = ensureRunBreak(beginIndex); 356 int endRunIndex = ensureRunBreak(endIndex); 357 358 Iterator iterator = attributes.entrySet().iterator(); 359 while (iterator.hasNext()) { 360 Map.Entry entry = (Map.Entry) iterator.next(); 361 addAttributeRunData((Attribute) entry.getKey(), entry.getValue(), beginRunIndex, endRunIndex); 362 } 363 } 364 365 private synchronized void addAttributeImpl(Attribute attribute, Object value, 366 int beginIndex, int endIndex) { 367 368 if (runCount == 0) { 370 createRunAttributeDataVectors(); 371 } 372 373 int beginRunIndex = ensureRunBreak(beginIndex); 375 int endRunIndex = ensureRunBreak(endIndex); 376 377 addAttributeRunData(attribute, value, beginRunIndex, endRunIndex); 378 } 379 380 private final void createRunAttributeDataVectors() { 381 int newRunStarts[] = new int[ARRAY_SIZE_INCREMENT]; 383 Vector newRunAttributes[] = new Vector[ARRAY_SIZE_INCREMENT]; 384 Vector newRunAttributeValues[] = new Vector[ARRAY_SIZE_INCREMENT]; 385 runStarts = newRunStarts; 386 runAttributes = newRunAttributes; 387 runAttributeValues = newRunAttributeValues; 388 runArraySize = ARRAY_SIZE_INCREMENT; 389 runCount = 1; } 391 392 private final int ensureRunBreak(int offset) { 394 return ensureRunBreak(offset, true); 395 } 396 397 408 private final int ensureRunBreak(int offset, boolean copyAttrs) { 409 if (offset == length()) { 410 return runCount; 411 } 412 413 int runIndex = 0; 415 while (runIndex < runCount && runStarts[runIndex] < offset) { 416 runIndex++; 417 } 418 419 if (runIndex < runCount && runStarts[runIndex] == offset) { 421 return runIndex; 422 } 423 424 if (runCount == runArraySize) { 427 int newArraySize = runArraySize + ARRAY_SIZE_INCREMENT; 428 int newRunStarts[] = new int[newArraySize]; 429 Vector newRunAttributes[] = new Vector[newArraySize]; 430 Vector newRunAttributeValues[] = new Vector[newArraySize]; 431 for (int i = 0; i < runArraySize; i++) { 432 newRunStarts[i] = runStarts[i]; 433 newRunAttributes[i] = runAttributes[i]; 434 newRunAttributeValues[i] = runAttributeValues[i]; 435 } 436 runStarts = newRunStarts; 437 runAttributes = newRunAttributes; 438 runAttributeValues = newRunAttributeValues; 439 runArraySize = newArraySize; 440 } 441 442 Vector newRunAttributes = null; 445 Vector newRunAttributeValues = null; 446 447 if (copyAttrs) { 448 Vector oldRunAttributes = runAttributes[runIndex - 1]; 449 Vector oldRunAttributeValues = runAttributeValues[runIndex - 1]; 450 if (oldRunAttributes != null) { 451 newRunAttributes = (Vector) oldRunAttributes.clone(); 452 } 453 if (oldRunAttributeValues != null) { 454 newRunAttributeValues = (Vector) oldRunAttributeValues.clone(); 455 } 456 } 457 458 runCount++; 460 for (int i = runCount - 1; i > runIndex; i--) { 461 runStarts[i] = runStarts[i - 1]; 462 runAttributes[i] = runAttributes[i - 1]; 463 runAttributeValues[i] = runAttributeValues[i - 1]; 464 } 465 runStarts[runIndex] = offset; 466 runAttributes[runIndex] = newRunAttributes; 467 runAttributeValues[runIndex] = newRunAttributeValues; 468 469 return runIndex; 470 } 471 472 private void addAttributeRunData(Attribute attribute, Object value, 474 int beginRunIndex, int endRunIndex) { 475 476 for (int i = beginRunIndex; i < endRunIndex; i++) { 477 int keyValueIndex = -1; if (runAttributes[i] == null) { 479 Vector newRunAttributes = new Vector(); 480 Vector newRunAttributeValues = new Vector(); 481 runAttributes[i] = newRunAttributes; 482 runAttributeValues[i] = newRunAttributeValues; 483 } else { 484 keyValueIndex = runAttributes[i].indexOf(attribute); 486 } 487 488 if (keyValueIndex == -1) { 489 int oldSize = runAttributes[i].size(); 491 runAttributes[i].addElement(attribute); 492 try { 493 runAttributeValues[i].addElement(value); 494 } 495 catch (Exception e) { 496 runAttributes[i].setSize(oldSize); 497 runAttributeValues[i].setSize(oldSize); 498 } 499 } else { 500 runAttributeValues[i].set(keyValueIndex, value); 502 } 503 } 504 } 505 506 512 public AttributedCharacterIterator getIterator() { 513 return getIterator(null, 0, length()); 514 } 515 516 527 public AttributedCharacterIterator getIterator(Attribute[] attributes) { 528 return getIterator(attributes, 0, length()); 529 } 530 531 547 public AttributedCharacterIterator getIterator(Attribute[] attributes, int beginIndex, int endIndex) { 548 return new AttributedStringIterator(attributes, beginIndex, endIndex); 549 } 550 551 554 int length() { 557 return text.length(); 558 } 559 560 private char charAt(int index) { 561 return text.charAt(index); 562 } 563 564 private synchronized Object getAttribute(Attribute attribute, int runIndex) { 565 Vector currentRunAttributes = runAttributes[runIndex]; 566 Vector currentRunAttributeValues = runAttributeValues[runIndex]; 567 if (currentRunAttributes == null) { 568 return null; 569 } 570 int attributeIndex = currentRunAttributes.indexOf(attribute); 571 if (attributeIndex != -1) { 572 return currentRunAttributeValues.elementAt(attributeIndex); 573 } 574 else { 575 return null; 576 } 577 } 578 579 private Object getAttributeCheckRange(Attribute attribute, int runIndex, int beginIndex, int endIndex) { 581 Object value = getAttribute(attribute, runIndex); 582 if (value instanceof Annotation ) { 583 if (beginIndex > 0) { 585 int currIndex = runIndex; 586 int runStart = runStarts[currIndex]; 587 while (runStart >= beginIndex && 588 valuesMatch(value, getAttribute(attribute, currIndex - 1))) { 589 currIndex--; 590 runStart = runStarts[currIndex]; 591 } 592 if (runStart < beginIndex) { 593 return null; 595 } 596 } 597 int textLength = length(); 598 if (endIndex < textLength) { 599 int currIndex = runIndex; 600 int runLimit = (currIndex < runCount - 1) ? runStarts[currIndex + 1] : textLength; 601 while (runLimit <= endIndex && 602 valuesMatch(value, getAttribute(attribute, currIndex + 1))) { 603 currIndex++; 604 runLimit = (currIndex < runCount - 1) ? runStarts[currIndex + 1] : textLength; 605 } 606 if (runLimit > endIndex) { 607 return null; 609 } 610 } 611 } 614 return value; 615 } 616 617 private boolean attributeValuesMatch(Set attributes, int runIndex1, int runIndex2) { 619 Iterator iterator = attributes.iterator(); 620 while (iterator.hasNext()) { 621 Attribute key = (Attribute) iterator.next(); 622 if (!valuesMatch(getAttribute(key, runIndex1), getAttribute(key, runIndex2))) { 623 return false; 624 } 625 } 626 return true; 627 } 628 629 private final static boolean valuesMatch(Object value1, Object value2) { 631 if (value1 == null) { 632 return value2 == null; 633 } else { 634 return value1.equals(value2); 635 } 636 } 637 638 642 private final void appendContents(StringBuffer buf, 643 CharacterIterator iterator) { 644 int index = iterator.getBeginIndex(); 645 int end = iterator.getEndIndex(); 646 647 while (index < end) { 648 iterator.setIndex(index++); 649 buf.append(iterator.current()); 650 } 651 } 652 653 658 private void setAttributes(Map attrs, int offset) { 659 if (runCount == 0) { 660 createRunAttributeDataVectors(); 661 } 662 663 int index = ensureRunBreak(offset, false); 664 int size; 665 666 if (attrs != null && (size = attrs.size()) > 0) { 667 Vector runAttrs = new Vector(size); 668 Vector runValues = new Vector(size); 669 Iterator iterator = attrs.entrySet().iterator(); 670 671 while (iterator.hasNext()) { 672 Map.Entry entry = (Map.Entry)iterator.next(); 673 674 runAttrs.add(entry.getKey()); 675 runValues.add(entry.getValue()); 676 } 677 runAttributes[index] = runAttrs; 678 runAttributeValues[index] = runValues; 679 } 680 } 681 682 685 private static boolean mapsDiffer(Map last, Map attrs) { 686 if (last == null) { 687 return (attrs != null && attrs.size() > 0); 688 } 689 return (!last.equals(attrs)); 690 } 691 692 693 695 final private class AttributedStringIterator implements AttributedCharacterIterator { 696 697 701 private int beginIndex; 703 private int endIndex; 704 705 private Attribute[] relevantAttributes; 707 708 private int currentIndex; 711 712 private int currentRunIndex; 714 private int currentRunStart; 715 private int currentRunLimit; 716 717 AttributedStringIterator(Attribute[] attributes, int beginIndex, int endIndex) { 719 720 if (beginIndex < 0 || beginIndex > endIndex || endIndex > length()) { 721 throw new IllegalArgumentException ("Invalid substring range"); 722 } 723 724 this.beginIndex = beginIndex; 725 this.endIndex = endIndex; 726 this.currentIndex = beginIndex; 727 updateRunInfo(); 728 if (attributes != null) { 729 relevantAttributes = (Attribute[]) attributes.clone(); 730 } 731 } 732 733 735 public boolean equals(Object obj) { 736 if (this == obj) { 737 return true; 738 } 739 if (!(obj instanceof AttributedStringIterator)) { 740 return false; 741 } 742 743 AttributedStringIterator that = (AttributedStringIterator) obj; 744 745 if (AttributedString.this != that.getString()) 746 return false; 747 if (currentIndex != that.currentIndex || beginIndex != that.beginIndex || endIndex != that.endIndex) 748 return false; 749 return true; 750 } 751 752 public int hashCode() { 753 return text.hashCode() ^ currentIndex ^ beginIndex ^ endIndex; 754 } 755 756 public Object clone() { 757 try { 758 AttributedStringIterator other = (AttributedStringIterator) super.clone(); 759 return other; 760 } 761 catch (CloneNotSupportedException e) { 762 throw new InternalError (); 763 } 764 } 765 766 768 public char first() { 769 return internalSetIndex(beginIndex); 770 } 771 772 public char last() { 773 if (endIndex == beginIndex) { 774 return internalSetIndex(endIndex); 775 } else { 776 return internalSetIndex(endIndex - 1); 777 } 778 } 779 780 public char current() { 781 if (currentIndex == endIndex) { 782 return DONE; 783 } else { 784 return charAt(currentIndex); 785 } 786 } 787 788 public char next() { 789 if (currentIndex < endIndex) { 790 return internalSetIndex(currentIndex + 1); 791 } 792 else { 793 return DONE; 794 } 795 } 796 797 public char previous() { 798 if (currentIndex > beginIndex) { 799 return internalSetIndex(currentIndex - 1); 800 } 801 else { 802 return DONE; 803 } 804 } 805 806 public char setIndex(int position) { 807 if (position < beginIndex || position > endIndex) 808 throw new IllegalArgumentException ("Invalid index"); 809 return internalSetIndex(position); 810 } 811 812 public int getBeginIndex() { 813 return beginIndex; 814 } 815 816 public int getEndIndex() { 817 return endIndex; 818 } 819 820 public int getIndex() { 821 return currentIndex; 822 } 823 824 826 public int getRunStart() { 827 return currentRunStart; 828 } 829 830 public int getRunStart(Attribute attribute) { 831 if (currentRunStart == beginIndex || currentRunIndex == -1) { 832 return currentRunStart; 833 } else { 834 Object value = getAttribute(attribute); 835 int runStart = currentRunStart; 836 int runIndex = currentRunIndex; 837 while (runStart > beginIndex && 838 valuesMatch(value, AttributedString.this.getAttribute(attribute, runIndex - 1))) { 839 runIndex--; 840 runStart = runStarts[runIndex]; 841 } 842 if (runStart < beginIndex) { 843 runStart = beginIndex; 844 } 845 return runStart; 846 } 847 } 848 849 public int getRunStart(Set<? extends Attribute> attributes) { 850 if (currentRunStart == beginIndex || currentRunIndex == -1) { 851 return currentRunStart; 852 } else { 853 int runStart = currentRunStart; 854 int runIndex = currentRunIndex; 855 while (runStart > beginIndex && 856 AttributedString.this.attributeValuesMatch(attributes, currentRunIndex, runIndex - 1)) { 857 runIndex--; 858 runStart = runStarts[runIndex]; 859 } 860 if (runStart < beginIndex) { 861 runStart = beginIndex; 862 } 863 return runStart; 864 } 865 } 866 867 public int getRunLimit() { 868 return currentRunLimit; 869 } 870 871 public int getRunLimit(Attribute attribute) { 872 if (currentRunLimit == endIndex || currentRunIndex == -1) { 873 return currentRunLimit; 874 } else { 875 Object value = getAttribute(attribute); 876 int runLimit = currentRunLimit; 877 int runIndex = currentRunIndex; 878 while (runLimit < endIndex && 879 valuesMatch(value, AttributedString.this.getAttribute(attribute, runIndex + 1))) { 880 runIndex++; 881 runLimit = runIndex < runCount - 1 ? runStarts[runIndex + 1] : endIndex; 882 } 883 if (runLimit > endIndex) { 884 runLimit = endIndex; 885 } 886 return runLimit; 887 } 888 } 889 890 public int getRunLimit(Set<? extends Attribute> attributes) { 891 if (currentRunLimit == endIndex || currentRunIndex == -1) { 892 return currentRunLimit; 893 } else { 894 int runLimit = currentRunLimit; 895 int runIndex = currentRunIndex; 896 while (runLimit < endIndex && 897 AttributedString.this.attributeValuesMatch(attributes, currentRunIndex, runIndex + 1)) { 898 runIndex++; 899 runLimit = runIndex < runCount - 1 ? runStarts[runIndex + 1] : endIndex; 900 } 901 if (runLimit > endIndex) { 902 runLimit = endIndex; 903 } 904 return runLimit; 905 } 906 } 907 908 public Map<Attribute,Object > getAttributes() { 909 if (runAttributes == null || currentRunIndex == -1 || runAttributes[currentRunIndex] == null) { 910 return new Hashtable(); 913 } 914 return new AttributeMap(currentRunIndex, beginIndex, endIndex); 915 } 916 917 public Set<Attribute> getAllAttributeKeys() { 918 if (runAttributes == null) { 920 return new HashSet(); 923 } 924 synchronized (AttributedString.this) { 925 Set keys = new HashSet(); 928 int i = 0; 929 while (i < runCount) { 930 if (runStarts[i] < endIndex && (i == runCount - 1 || runStarts[i + 1] > beginIndex)) { 931 Vector currentRunAttributes = runAttributes[i]; 932 if (currentRunAttributes != null) { 933 int j = currentRunAttributes.size(); 934 while (j-- > 0) { 935 keys.add(currentRunAttributes.get(j)); 936 } 937 } 938 } 939 i++; 940 } 941 return keys; 942 } 943 } 944 945 public Object getAttribute(Attribute attribute) { 946 int runIndex = currentRunIndex; 947 if (runIndex < 0) { 948 return null; 949 } 950 return AttributedString.this.getAttributeCheckRange(attribute, runIndex, beginIndex, endIndex); 951 } 952 953 955 private AttributedString getString() { 956 return AttributedString.this; 957 } 958 959 private char internalSetIndex(int position) { 962 currentIndex = position; 963 if (position < currentRunStart || position >= currentRunLimit) { 964 updateRunInfo(); 965 } 966 if (currentIndex == endIndex) { 967 return DONE; 968 } else { 969 return charAt(position); 970 } 971 } 972 973 private void updateRunInfo() { 975 if (currentIndex == endIndex) { 976 currentRunStart = currentRunLimit = endIndex; 977 currentRunIndex = -1; 978 } else { 979 synchronized (AttributedString.this) { 980 int runIndex = -1; 981 while (runIndex < runCount - 1 && runStarts[runIndex + 1] <= currentIndex) 982 runIndex++; 983 currentRunIndex = runIndex; 984 if (runIndex >= 0) { 985 currentRunStart = runStarts[runIndex]; 986 if (currentRunStart < beginIndex) 987 currentRunStart = beginIndex; 988 } 989 else { 990 currentRunStart = beginIndex; 991 } 992 if (runIndex < runCount - 1) { 993 currentRunLimit = runStarts[runIndex + 1]; 994 if (currentRunLimit > endIndex) 995 currentRunLimit = endIndex; 996 } 997 else { 998 currentRunLimit = endIndex; 999 } 1000 } 1001 } 1002 } 1003 1004 } 1005 1006 1008 final private class AttributeMap extends AbstractMap<Attribute,Object > { 1009 1010 int runIndex; 1011 int beginIndex; 1012 int endIndex; 1013 1014 AttributeMap(int runIndex, int beginIndex, int endIndex) { 1015 this.runIndex = runIndex; 1016 this.beginIndex = beginIndex; 1017 this.endIndex = endIndex; 1018 } 1019 1020 public Set entrySet() { 1021 HashSet set = new HashSet(); 1022 synchronized (AttributedString.this) { 1023 int size = runAttributes[runIndex].size(); 1024 for (int i = 0; i < size; i++) { 1025 Attribute key = (Attribute) runAttributes[runIndex].get(i); 1026 Object value = runAttributeValues[runIndex].get(i); 1027 if (value instanceof Annotation ) { 1028 value = AttributedString.this.getAttributeCheckRange(key, 1029 runIndex, beginIndex, endIndex); 1030 if (value == null) { 1031 continue; 1032 } 1033 } 1034 Map.Entry entry = new AttributeEntry(key, value); 1035 set.add(entry); 1036 } 1037 } 1038 return set; 1039 } 1040 1041 public Object get(Object key) { 1042 return AttributedString.this.getAttributeCheckRange((Attribute) key, runIndex, beginIndex, endIndex); 1043 } 1044 } 1045} 1046 1047class AttributeEntry implements Map.Entry { 1048 1049 private Attribute key; 1050 private Object value; 1051 1052 AttributeEntry(Attribute key, Object value) { 1053 this.key = key; 1054 this.value = value; 1055 } 1056 1057 public boolean equals(Object o) { 1058 if (!(o instanceof AttributeEntry)) { 1059 return false; 1060 } 1061 AttributeEntry other = (AttributeEntry) o; 1062 return other.key.equals(key) && 1063 (value == null ? other.value == null : other.value.equals(value)); 1064 } 1065 1066 public Object getKey() { 1067 return key; 1068 } 1069 1070 public Object getValue() { 1071 return value; 1072 } 1073 1074 public Object setValue(Object newValue) { 1075 throw new UnsupportedOperationException (); 1076 } 1077 1078 public int hashCode() { 1079 return key.hashCode() ^ (value==null ? 0 : value.hashCode()); 1080 } 1081 1082 public String toString() { 1083 return key.toString()+"="+value.toString(); 1084 } 1085} 1086 | Popular Tags |