| 1 16 package org.apache.commons.collections; 17 18 import java.io.IOException ; 19 import java.io.ObjectInputStream ; 20 import java.io.ObjectOutputStream ; 21 import java.io.Serializable ; 22 import java.lang.reflect.Array ; 23 import java.util.ArrayList ; 24 import java.util.Collection ; 25 import java.util.ConcurrentModificationException ; 26 import java.util.Iterator ; 27 import java.util.List ; 28 import java.util.ListIterator ; 29 import java.util.NoSuchElementException ; 30 import java.lang.ref.WeakReference ; 31 32 54 public class CursorableLinkedList implements List , Serializable { 55 56 private static final long serialVersionUID = 8836393098519411393L; 57 58 60 66 public boolean add(Object o) { 67 insertListable(_head.prev(),null,o); 68 return true; 69 } 70 71 86 public void add(int index, Object element) { 87 if(index == _size) { 88 add(element); 89 } else { 90 if(index < 0 || index > _size) { 91 throw new IndexOutOfBoundsException (String.valueOf(index) + " < 0 or " + String.valueOf(index) + " > " + _size); 92 } 93 Listable succ = (isEmpty() ? null : getListableAt(index)); 94 Listable pred = (null == succ ? null : succ.prev()); 95 insertListable(pred,succ,element); 96 } 97 } 98 99 116 public boolean addAll(Collection c) { 117 if(c.isEmpty()) { 118 return false; 119 } 120 Iterator it = c.iterator(); 121 while(it.hasNext()) { 122 insertListable(_head.prev(),null,it.next()); 123 } 124 return true; 125 } 126 127 152 public boolean addAll(int index, Collection c) { 153 if(c.isEmpty()) { 154 return false; 155 } else if(_size == index || _size == 0) { 156 return addAll(c); 157 } else { 158 Listable succ = getListableAt(index); 159 Listable pred = (null == succ) ? null : succ.prev(); 160 Iterator it = c.iterator(); 161 while(it.hasNext()) { 162 pred = insertListable(pred,succ,it.next()); 163 } 164 return true; 165 } 166 } 167 168 175 public boolean addFirst(Object o) { 176 insertListable(null,_head.next(),o); 177 return true; 178 } 179 180 187 public boolean addLast(Object o) { 188 insertListable(_head.prev(),null,o); 189 return true; 190 } 191 192 197 public void clear() { 198 206 Iterator it = iterator(); 207 while(it.hasNext()) { 208 it.next(); 209 it.remove(); 210 } 211 } 212 213 222 public boolean contains(Object o) { 223 for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { 224 if((null == o && null == elt.value()) || 225 (o != null && o.equals(elt.value()))) { 226 return true; 227 } 228 } 229 return false; 230 } 231 232 240 public boolean containsAll(Collection c) { 241 Iterator it = c.iterator(); 242 while(it.hasNext()) { 243 if(!this.contains(it.next())) { 244 return false; 245 } 246 } 247 return true; 248 } 249 250 275 public CursorableLinkedList.Cursor cursor() { 276 return new Cursor(0); 277 } 278 279 295 public CursorableLinkedList.Cursor cursor(int i) { 296 return new Cursor(i); 297 } 298 299 313 public boolean equals(Object o) { 314 if(o == this) { 315 return true; 316 } else if(!(o instanceof List )) { 317 return false; 318 } 319 Iterator it = ((List )o).listIterator(); 320 for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { 321 if(!it.hasNext() || (null == elt.value() ? null != it.next() : !(elt.value().equals(it.next()))) ) { 322 return false; 323 } 324 } 325 return !it.hasNext(); 326 } 327 328 337 public Object get(int index) { 338 return getListableAt(index).value(); 339 } 340 341 344 public Object getFirst() { 345 try { 346 return _head.next().value(); 347 } catch(NullPointerException e) { 348 throw new NoSuchElementException (); 349 } 350 } 351 352 355 public Object getLast() { 356 try { 357 return _head.prev().value(); 358 } catch(NullPointerException e) { 359 throw new NoSuchElementException (); 360 } 361 } 362 363 384 public int hashCode() { 385 int hash = 1; 386 for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { 387 hash = 31*hash + (null == elt.value() ? 0 : elt.value().hashCode()); 388 } 389 return hash; 390 } 391 392 403 public int indexOf(Object o) { 404 int ndx = 0; 405 406 if (null == o) { 409 for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { 410 if (null == elt.value()) { 411 return ndx; 412 } 413 ndx++; 414 } 415 } else { 416 417 for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { 418 if (o.equals(elt.value())) { 419 return ndx; 420 } 421 ndx++; 422 } 423 } 424 return -1; 425 } 426 427 431 public boolean isEmpty() { 432 return(0 == _size); 433 } 434 435 439 public Iterator iterator() { 440 return listIterator(0); 441 } 442 443 454 public int lastIndexOf(Object o) { 455 int ndx = _size-1; 456 457 if (null == o) { 460 for(Listable elt = _head.prev(), past = null; null != elt && past != _head.next(); elt = (past = elt).prev()) { 461 if (null == elt.value()) { 462 return ndx; 463 } 464 ndx--; 465 } 466 } else { 467 for(Listable elt = _head.prev(), past = null; null != elt && past != _head.next(); elt = (past = elt).prev()) { 468 if (o.equals(elt.value())) { 469 return ndx; 470 } 471 ndx--; 472 } 473 } 474 return -1; 475 } 476 477 481 public ListIterator listIterator() { 482 return listIterator(0); 483 } 484 485 489 public ListIterator listIterator(int index) { 490 if(index<0 || index > _size) { 491 throw new IndexOutOfBoundsException (index + " < 0 or > " + _size); 492 } 493 return new ListIter(index); 494 } 495 496 506 public boolean remove(Object o) { 507 for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { 508 if(null == o && null == elt.value()) { 509 removeListable(elt); 510 return true; 511 } else if(o != null && o.equals(elt.value())) { 512 removeListable(elt); 513 return true; 514 } 515 } 516 return false; 517 } 518 519 531 public Object remove(int index) { 532 Listable elt = getListableAt(index); 533 Object ret = elt.value(); 534 removeListable(elt); 535 return ret; 536 } 537 538 546 public boolean removeAll(Collection c) { 547 if(0 == c.size() || 0 == _size) { 548 return false; 549 } else { 550 boolean changed = false; 551 Iterator it = iterator(); 552 while(it.hasNext()) { 553 if(c.contains(it.next())) { 554 it.remove(); 555 changed = true; 556 } 557 } 558 return changed; 559 } 560 } 561 562 565 public Object removeFirst() { 566 if(_head.next() != null) { 567 Object val = _head.next().value(); 568 removeListable(_head.next()); 569 return val; 570 } else { 571 throw new NoSuchElementException (); 572 } 573 } 574 575 578 public Object removeLast() { 579 if(_head.prev() != null) { 580 Object val = _head.prev().value(); 581 removeListable(_head.prev()); 582 return val; 583 } else { 584 throw new NoSuchElementException (); 585 } 586 } 587 588 598 public boolean retainAll(Collection c) { 599 boolean changed = false; 600 Iterator it = iterator(); 601 while(it.hasNext()) { 602 if(!c.contains(it.next())) { 603 it.remove(); 604 changed = true; 605 } 606 } 607 return changed; 608 } 609 610 625 public Object set(int index, Object element) { 626 Listable elt = getListableAt(index); 627 Object val = elt.setValue(element); 628 broadcastListableChanged(elt); 629 return val; 630 } 631 632 636 public int size() { 637 return _size; 638 } 639 640 647 public Object [] toArray() { 648 Object [] array = new Object [_size]; 649 int i = 0; 650 for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { 651 array[i++] = elt.value(); 652 } 653 return array; 654 } 655 656 671 public Object [] toArray(Object a[]) { 672 if(a.length < _size) { 673 a = (Object [])Array.newInstance(a.getClass().getComponentType(), _size); 674 } 675 int i = 0; 676 for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { 677 a[i++] = elt.value(); 678 } 679 if(a.length > _size) { 680 a[_size] = null; } 682 return a; 683 } 684 685 689 public String toString() { 690 StringBuffer buf = new StringBuffer (); 691 buf.append("["); 692 for(Listable elt = _head.next(), past = null; null != elt && past != _head.prev(); elt = (past = elt).next()) { 693 if(_head.next() != elt) { 694 buf.append(", "); 695 } 696 buf.append(elt.value()); 697 } 698 buf.append("]"); 699 return buf.toString(); 700 } 701 702 706 public List subList(int i, int j) { 707 if(i < 0 || j > _size || i > j) { 708 throw new IndexOutOfBoundsException (); 709 } else if(i == 0 && j == _size) { 710 return this; 711 } else { 712 return new CursorableSubList(this,i,j); 713 } 714 } 715 716 718 726 protected Listable insertListable(Listable before, Listable after, Object value) { 727 _modCount++; 728 _size++; 729 Listable elt = new Listable(before,after,value); 730 if(null != before) { 731 before.setNext(elt); 732 } else { 733 _head.setNext(elt); 734 } 735 736 if(null != after) { 737 after.setPrev(elt); 738 } else { 739 _head.setPrev(elt); 740 } 741 broadcastListableInserted(elt); 742 return elt; 743 } 744 745 750 protected void removeListable(Listable elt) { 751 _modCount++; 752 _size--; 753 if(_head.next() == elt) { 754 _head.setNext(elt.next()); 755 } 756 if(null != elt.next()) { 757 elt.next().setPrev(elt.prev()); 758 } 759 if(_head.prev() == elt) { 760 _head.setPrev(elt.prev()); 761 } 762 if(null != elt.prev()) { 763 elt.prev().setNext(elt.next()); 764 } 765 broadcastListableRemoved(elt); 766 } 767 768 776 protected Listable getListableAt(int index) { 777 if(index < 0 || index >= _size) { 778 throw new IndexOutOfBoundsException (String.valueOf(index) + " < 0 or " + String.valueOf(index) + " >= " + _size); 779 } 780 if(index <=_size/2) { 781 Listable elt = _head.next(); 782 for(int i = 0; i < index; i++) { 783 elt = elt.next(); 784 } 785 return elt; 786 } else { 787 Listable elt = _head.prev(); 788 for(int i = (_size-1); i > index; i--) { 789 elt = elt.prev(); 790 } 791 return elt; 792 } 793 } 794 795 799 protected void registerCursor(Cursor cur) { 800 for (Iterator it = _cursors.iterator(); it.hasNext(); ) { 803 WeakReference ref = (WeakReference ) it.next(); 804 if (ref.get() == null) { 805 it.remove(); 806 } 807 } 808 809 _cursors.add( new WeakReference (cur) ); 810 } 811 812 816 protected void unregisterCursor(Cursor cur) { 817 for (Iterator it = _cursors.iterator(); it.hasNext(); ) { 818 WeakReference ref = (WeakReference ) it.next(); 819 Cursor cursor = (Cursor) ref.get(); 820 if (cursor == null) { 821 it.remove(); 825 826 } else if (cursor == cur) { 827 ref.clear(); 828 it.remove(); 829 break; 830 } 831 } 832 } 833 834 838 protected void invalidateCursors() { 839 Iterator it = _cursors.iterator(); 840 while (it.hasNext()) { 841 WeakReference ref = (WeakReference ) it.next(); 842 Cursor cursor = (Cursor) ref.get(); 843 if (cursor != null) { 844 cursor.invalidate(); 846 ref.clear(); 847 } 848 it.remove(); 849 } 850 } 851 852 857 protected void broadcastListableChanged(Listable elt) { 858 Iterator it = _cursors.iterator(); 859 while (it.hasNext()) { 860 WeakReference ref = (WeakReference ) it.next(); 861 Cursor cursor = (Cursor) ref.get(); 862 if (cursor == null) { 863 it.remove(); } else { 865 cursor.listableChanged(elt); 866 } 867 } 868 } 869 870 874 protected void broadcastListableRemoved(Listable elt) { 875 Iterator it = _cursors.iterator(); 876 while (it.hasNext()) { 877 WeakReference ref = (WeakReference ) it.next(); 878 Cursor cursor = (Cursor) ref.get(); 879 if (cursor == null) { 880 it.remove(); } else { 882 cursor.listableRemoved(elt); 883 } 884 } 885 } 886 887 891 protected void broadcastListableInserted(Listable elt) { 892 &
|