1 16 package org.apache.commons.collections.list; 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.ref.WeakReference ; 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 30 62 public class CursorableLinkedList extends AbstractLinkedList implements Serializable { 63 64 65 private static final long serialVersionUID = 8836393098519411393L; 66 67 68 protected transient List cursors = new ArrayList (); 69 70 74 public CursorableLinkedList() { 75 super(); 76 init(); } 78 79 84 public CursorableLinkedList(Collection coll) { 85 super(coll); 86 } 87 88 92 protected void init() { 93 super.init(); 94 cursors = new ArrayList (); 95 } 96 97 107 public Iterator iterator() { 108 return super.listIterator(0); 109 } 110 111 126 public ListIterator listIterator() { 127 return cursor(0); 128 } 129 130 146 public ListIterator listIterator(int fromIndex) { 147 return cursor(fromIndex); 148 } 149 150 173 public CursorableLinkedList.Cursor cursor() { 174 return cursor(0); 175 } 176 177 204 public CursorableLinkedList.Cursor cursor(int fromIndex) { 205 Cursor cursor = new Cursor(this, fromIndex); 206 registerCursor(cursor); 207 return cursor; 208 } 209 210 219 protected void updateNode(Node node, Object value) { 220 super.updateNode(node, value); 221 broadcastNodeChanged(node); 222 } 223 224 231 protected void addNode(Node nodeToInsert, Node insertBeforeNode) { 232 super.addNode(nodeToInsert, insertBeforeNode); 233 broadcastNodeInserted(nodeToInsert); 234 } 235 236 242 protected void removeNode(Node node) { 243 super.removeNode(node); 244 broadcastNodeRemoved(node); 245 } 246 247 250 protected void removeAllNodes() { 251 if (size() > 0) { 252 Iterator it = iterator(); 254 while (it.hasNext()) { 255 it.next(); 256 it.remove(); 257 } 258 } 259 } 260 261 267 protected void registerCursor(Cursor cursor) { 268 for (Iterator it = cursors.iterator(); it.hasNext();) { 271 WeakReference ref = (WeakReference ) it.next(); 272 if (ref.get() == null) { 273 it.remove(); 274 } 275 } 276 cursors.add(new WeakReference (cursor)); 277 } 278 279 284 protected void unregisterCursor(Cursor cursor) { 285 for (Iterator it = cursors.iterator(); it.hasNext();) { 286 WeakReference ref = (WeakReference ) it.next(); 287 Cursor cur = (Cursor) ref.get(); 288 if (cur == null) { 289 it.remove(); 293 294 } else if (cur == cursor) { 295 ref.clear(); 296 it.remove(); 297 break; 298 } 299 } 300 } 301 302 309 protected void broadcastNodeChanged(Node node) { 310 Iterator it = cursors.iterator(); 311 while (it.hasNext()) { 312 WeakReference ref = (WeakReference ) it.next(); 313 Cursor cursor = (Cursor) ref.get(); 314 if (cursor == null) { 315 it.remove(); } else { 317 cursor.nodeChanged(node); 318 } 319 } 320 } 321 322 328 protected void broadcastNodeRemoved(Node node) { 329 Iterator it = cursors.iterator(); 330 while (it.hasNext()) { 331 WeakReference ref = (WeakReference ) it.next(); 332 Cursor cursor = (Cursor) ref.get(); 333 if (cursor == null) { 334 it.remove(); } else { 336 cursor.nodeRemoved(node); 337 } 338 } 339 } 340 341 347 protected void broadcastNodeInserted(Node node) { 348 Iterator it = cursors.iterator(); 349 while (it.hasNext()) { 350 WeakReference ref = (WeakReference ) it.next(); 351 Cursor cursor = (Cursor) ref.get(); 352 if (cursor == null) { 353 it.remove(); } else { 355 cursor.nodeInserted(node); 356 } 357 } 358 } 359 360 364 private void writeObject(ObjectOutputStream out) throws IOException { 365 out.defaultWriteObject(); 366 doWriteObject(out); 367 } 368 369 372 private void readObject(ObjectInputStream in) throws IOException , ClassNotFoundException { 373 in.defaultReadObject(); 374 doReadObject(in); 375 } 376 377 382 public static class Cursor extends AbstractLinkedList.LinkedListIterator { 383 384 boolean valid = true; 385 386 boolean nextIndexValid = true; 387 388 393 protected Cursor(CursorableLinkedList parent, int index) { 394 super(parent, index); 395 valid = true; 396 } 397 398 404 public void add(Object obj) { 405 super.add(obj); 406 next = next.next; 408 } 409 410 415 public int nextIndex() { 416 if (nextIndexValid == false) { 417 if (next == parent.header) { 418 nextIndex = parent.size(); 419 } else { 420 int pos = 0; 421 Node temp = parent.header.next; 422 while (temp != next) { 423 pos++; 424 temp = temp.next; 425 } 426 nextIndex = pos; 427 } 428 nextIndexValid = true; 429 } 430 return nextIndex; 431 } 432 433 438 protected void nodeChanged(Node node) { 439 } 441 442 447 protected void nodeRemoved(Node node) { 448 if (node == next) { 449 next = node.next; 450 } else if (node == current) { 451 current = null; 452 nextIndex--; 453 } else { 454 nextIndexValid = false; 455 } 456 } 457 458 463 protected void nodeInserted(Node node) { 464 if (node.previous == current) { 465 next = node; 466 } else if (next.previous == node) { 467 next = node; 468 } else { 469 nextIndexValid = false; 470 } 471 } 472 473 476 protected void checkModCount() { 477 if (!valid) { 478 throw new ConcurrentModificationException ("Cursor closed"); 479 } 480 } 481 482 490 public void close() { 491 if (valid) { 492 ((CursorableLinkedList) parent).unregisterCursor(this); 493 valid = false; 494 } 495 } 496 } 497 } 498 | Popular Tags |