1 16 package org.apache.axis.collections; 17 18 import org.apache.axis.i18n.Messages; 19 20 import java.io.Externalizable ; 21 import java.io.IOException ; 22 import java.io.ObjectInput ; 23 import java.io.ObjectOutput ; 24 import java.util.AbstractCollection ; 25 import java.util.AbstractSet ; 26 import java.util.ArrayList ; 27 import java.util.Collection ; 28 import java.util.Collections ; 29 import java.util.ConcurrentModificationException ; 30 import java.util.HashMap ; 31 import java.util.Iterator ; 32 import java.util.List ; 33 import java.util.Map ; 34 import java.util.NoSuchElementException ; 35 import java.util.Set ; 36 37 58 public class SequencedHashMap implements Map , Cloneable , Externalizable { 59 60 64 private static class Entry implements Map.Entry { 65 75 private final Object key; 76 private Object value; 77 78 Entry next = null; 81 Entry prev = null; 82 83 public Entry(Object key, Object value) { 84 this.key = key; 85 this.value = value; 86 } 87 88 public Object getKey() { 90 return this.key; 91 } 92 93 public Object getValue() { 95 return this.value; 96 } 97 98 public Object setValue(Object value) { 100 Object oldValue = this.value; 101 this.value = value; 102 return oldValue; 103 } 104 105 public int hashCode() { 106 return ((getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode())); 108 } 109 110 public boolean equals(Object obj) { 111 if (obj == null) 112 return false; 113 if (obj == this) 114 return true; 115 if (!(obj instanceof Map.Entry )) 116 return false; 117 118 Map.Entry other = (Map.Entry ) obj; 119 120 return ( 122 (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey())) 123 && (getValue() == null ? other.getValue() == null : getValue().equals(other.getValue()))); 124 } 125 public String toString() { 126 return "[" + getKey() + "=" + getValue() + "]"; 127 } 128 } 129 130 135 private static final Entry createSentinel() { 136 Entry s = new Entry(null, null); 137 s.prev = s; 138 s.next = s; 139 return s; 140 } 141 142 145 private Entry sentinel; 146 147 150 private HashMap entries; 151 152 158 private transient long modCount = 0; 159 160 164 public SequencedHashMap() { 165 sentinel = createSentinel(); 166 entries = new HashMap (); 167 } 168 169 177 public SequencedHashMap(int initialSize) { 178 sentinel = createSentinel(); 179 entries = new HashMap (initialSize); 180 } 181 182 192 public SequencedHashMap(int initialSize, float loadFactor) { 193 sentinel = createSentinel(); 194 entries = new HashMap (initialSize, loadFactor); 195 } 196 197 202 public SequencedHashMap(Map m) { 203 this(); 204 putAll(m); 205 } 206 207 211 private void removeEntry(Entry entry) { 212 entry.next.prev = entry.prev; 213 entry.prev.next = entry.next; 214 } 215 216 220 private void insertEntry(Entry entry) { 221 entry.next = sentinel; 222 entry.prev = sentinel.prev; 223 sentinel.prev.next = entry; 224 sentinel.prev = entry; 225 } 226 227 229 232 public int size() { 233 return entries.size(); 235 } 236 237 240 public boolean isEmpty() { 241 return sentinel.next == sentinel; 244 } 245 246 249 public boolean containsKey(Object key) { 250 return entries.containsKey(key); 252 } 253 254 257 public boolean containsValue(Object value) { 258 263 if (value == null) { 267 for (Entry pos = sentinel.next; pos != sentinel; pos = pos.next) { 268 if (pos.getValue() == null) 269 return true; 270 } 271 } else { 272 for (Entry pos = sentinel.next; pos != sentinel; pos = pos.next) { 273 if (value.equals(pos.getValue())) 274 return true; 275 } 276 } 277 return false; 278 } 279 280 283 public Object get(Object o) { 284 Entry entry = (Entry) entries.get(o); 286 if (entry == null) 287 return null; 288 289 return entry.getValue(); 290 } 291 292 302 public Map.Entry getFirst() { 303 return (isEmpty()) ? null : sentinel.next; 307 } 308 309 319 public Object getFirstKey() { 320 return sentinel.next.getKey(); 327 } 328 329 339 public Object getFirstValue() { 340 return sentinel.next.getValue(); 347 } 348 349 369 public Map.Entry getLast() { 370 return (isEmpty()) ? null : sentinel.prev; 374 } 375 376 386 public Object getLastKey() { 387 return sentinel.prev.getKey(); 394 } 395 396 406 public Object getLastValue() { 407 return sentinel.prev.getValue(); 414 } 415 416 419 public Object put(Object key, Object value) { 420 modCount++; 421 422 Object oldValue = null; 423 424 Entry e = (Entry) entries.get(key); 426 427 if (e != null) { 429 removeEntry(e); 431 432 oldValue = e.setValue(value); 434 435 } else { 441 e = new Entry(key, value); 443 entries.put(key, e); 444 } 445 447 insertEntry(e); 449 450 return oldValue; 451 } 452 453 456 public Object remove(Object key) { 457 Entry e = removeImpl(key); 458 return (e == null) ? null : e.getValue(); 459 } 460 461 465 private Entry removeImpl(Object key) { 466 Entry e = (Entry) entries.remove(key); 467 if (e == null) 468 return null; 469 modCount++; 470 removeEntry(e); 471 return e; 472 } 473 474 484 public void putAll(Map t) { 485 Iterator iter = t.entrySet().iterator(); 486 while (iter.hasNext()) { 487 Map.Entry entry = (Map.Entry ) iter.next(); 488 put(entry.getKey(), entry.getValue()); 489 } 490 } 491 492 495 public void clear() { 496 modCount++; 497 498 entries.clear(); 500 501 sentinel.next = sentinel; 503 sentinel.prev = sentinel; 504 } 505 506 509 public boolean equals(Object obj) { 510 if (obj == null) 511 return false; 512 if (obj == this) 513 return true; 514 515 if (!(obj instanceof Map )) 516 return false; 517 518 return entrySet().equals(((Map ) obj).entrySet()); 519 } 520 521 524 public int hashCode() { 525 return entrySet().hashCode(); 526 } 527 528 535 public String toString() { 536 StringBuffer buf = new StringBuffer (); 537 buf.append('['); 538 for (Entry pos = sentinel.next; pos != sentinel; pos = pos.next) { 539 buf.append(pos.getKey()); 540 buf.append('='); 541 buf.append(pos.getValue()); 542 if (pos.next != sentinel) { 543 buf.append(','); 544 } 545 } 546 buf.append(']'); 547 548 return buf.toString(); 549 } 550 551 554 public Set keySet() { 555 return new AbstractSet () { 556 557 public Iterator iterator() { 559 return new OrderedIterator(KEY); 560 } 561 public boolean remove(Object o) { 562 Entry e = SequencedHashMap.this.removeImpl(o); 563 return (e != null); 564 } 565 566 public void clear() { 568 SequencedHashMap.this.clear(); 569 } 570 public int size() { 571 return SequencedHashMap.this.size(); 572 } 573 public boolean isEmpty() { 574 return SequencedHashMap.this.isEmpty(); 575 } 576 public boolean contains(Object o) { 577 return SequencedHashMap.this.containsKey(o); 578 } 579 580 }; 581 } 582 583 586 public Collection values() { 587 return new AbstractCollection () { 588 public Iterator iterator() { 590 return new OrderedIterator(VALUE); 591 } 592 public boolean remove(Object value) { 593 if (value == null) { 597 for (Entry pos = sentinel.next; pos != sentinel; pos = pos.next) { 598 if (pos.getValue() == null) { 599 SequencedHashMap.this.removeImpl(pos.getKey()); 600 return true; 601 } 602 } 603 } else { 604 for (Entry pos = sentinel.next; pos != sentinel; pos = pos.next) { 605 if (value.equals(pos.getValue())) { 606 SequencedHashMap.this.removeImpl(pos.getKey()); 607 return true; 608 } 609 } 610 } 611 612 return false; 613 } 614 615 public void clear() { 617 SequencedHashMap.this.clear(); 618 } 619 public int size() { 620 return SequencedHashMap.this.size(); 621 } 622 public boolean isEmpty() { 623 return SequencedHashMap.this.isEmpty(); 624 } 625 public boolean contains(Object o) { 626 return SequencedHashMap.this.containsValue(o); 627 } 628 }; 629 } 630 631 634 public Set entrySet() { 635 return new AbstractSet () { 636 private Entry findEntry(Object o) { 638 if (o == null) 639 return null; 640 if (!(o instanceof Map.Entry )) 641 return null; 642 643 Map.Entry e = (Map.Entry ) o; 644 Entry entry = (Entry) entries.get(e.getKey()); 645 if (entry != null && entry.equals(e)) 646 return entry; 647 else 648 return null; 649 } 650 651 public Iterator iterator() { 653 return new OrderedIterator(ENTRY); 654 } 655 public boolean remove(Object o) { 656 Entry e = findEntry(o); 657 if (e == null) 658 return false; 659 660 return SequencedHashMap.this.removeImpl(e.getKey()) != null; 661 } 662 663 public void clear() { 665 SequencedHashMap.this.clear(); 666 } 667 public int size() { 668 return SequencedHashMap.this.size(); 669 } 670 public boolean isEmpty() { 671 return SequencedHashMap.this.isEmpty(); 672 } 673 public boolean contains(Object o) { 674 return findEntry(o) != null; 675 } 676 }; 677 } 678 679 private static final int KEY = 0; 681 private static final int VALUE = 1; 682 private static final int ENTRY = 2; 683 private static final int REMOVED_MASK = 0x80000000; 684 685 private class OrderedIterator implements Iterator { 686 695 private int returnType; 696 697 701 private Entry pos = sentinel; 702 703 708 private transient long expectedModCount = modCount; 709 710 716 public OrderedIterator(int returnType) { 717 this.returnType = returnType | REMOVED_MASK; 720 } 721 722 729 public boolean hasNext() { 730 return pos.next != sentinel; 731 } 732 733 744 public Object next() { 745 if (modCount != expectedModCount) { 746 throw new ConcurrentModificationException (Messages.getMessage("seqHashMapConcurrentModificationException00")); 747 } 748 if (pos.next == sentinel) { 749 throw new NoSuchElementException (Messages.getMessage("seqHashMapNoSuchElementException00")); 750 } 751 752 returnType = returnType & ~REMOVED_MASK; 754 755 pos = pos.next; 756 switch (returnType) { 757 case KEY : 758 return pos.getKey(); 759 case VALUE : 760 return pos.getValue(); 761 case ENTRY : 762 return pos; 763 default : 764 throw new Error (Messages.getMessage("seqHashMapBadIteratorType01", new Integer (returnType).toString())); 766 } 767 768 } 769 770 781 public void remove() { 782 if ((returnType & REMOVED_MASK) != 0) { 783 throw new IllegalStateException (Messages.getMessage("seqHashMapIllegalStateException00")); 784 } 785 if (modCount != expectedModCount) { 786 throw new ConcurrentModificationException (Messages.getMessage("seqHashMapConcurrentModificationException00")); 787 } 788 789 SequencedHashMap.this.removeImpl(pos.getKey()); 790 791 expectedModCount++; 793 794 returnType = returnType | REMOVED_MASK; 796 } 797 } 798 799 802 812 public Object clone() throws CloneNotSupportedException { 813 SequencedHashMap map = (SequencedHashMap) super.clone(); 818 819 map.sentinel = createSentinel(); 821 822 map.entries = new HashMap (); 825 826 map.putAll(this); 828 829 837 return map; 838 } 839 840 846 private Map.Entry getEntry(int index) { 847 Entry pos = sentinel; 848 849 if (index < 0) { 850 throw new ArrayIndexOutOfBoundsException (Messages.getMessage("seqHashMapArrayIndexOutOfBoundsException01", new Integer (index).toString())); 851 } 852 853 int i = -1; 855 while (i < (index - 1) && pos.next != sentinel) { 856 i++; 857 pos = pos.next; 858 } 859 861 if (pos.next == sentinel) { 863 throw new ArrayIndexOutOfBoundsException (Messages.getMessage("seqHashMapArrayIndexOutOfBoundsException02", 864 new Integer (index).toString(), 865 new Integer (i + 1).toString())); 866 } 867 868 return pos.next; 869 } 870 871 879 public Object get(int index) { 880 return getEntry(index).getKey(); 881 } 882 883 891 public Object getValue(int index) { 892 return getEntry(index).getValue(); 893 } 894 895 901 public int indexOf(Object key) { 902 Entry e = (Entry) entries.get(key); 903 if (e == null) { 904 return -1; 905 } 906 int pos = 0; 907 while (e.prev != sentinel) { 908 pos++; 909 e = e.prev; 910 } 911 return pos; 912 } 913 914 919 public Iterator iterator() { 920 return keySet().iterator(); 921 } 922 923 929 public int lastIndexOf(Object key) { 930 return indexOf(key); 932 } 933 934 948 public List sequence() { 949 List l = new ArrayList (size()); 950 Iterator iter = keySet().iterator(); 951 while (iter.hasNext()) { 952 l.add(iter.next()); 953 } 954 955 return Collections.unmodifiableList(l); 956 } 957 958 968 public Object remove(int index) { 969 return remove(get(index)); 970 } 971 972 974 981 public void readExternal(ObjectInput in) throws IOException , ClassNotFoundException { 982 int size = in.readInt(); 983 for (int i = 0; i < size; i++) { 984 Object key = in.readObject(); 985 Object value = in.readObject(); 986 put(key, value); 987 } 988 } 989 990 996 public void writeExternal(ObjectOutput out) throws IOException { 997 out.writeInt(size()); 998 for (Entry pos = sentinel.next; pos != sentinel; pos = pos.next) { 999 out.writeObject(pos.getKey()); 1000 out.writeObject(pos.getValue()); 1001 } 1002 } 1003 1004 private static final long serialVersionUID = 3380552487888102930L; 1007 1008} 1009 | Popular Tags |