1 19 package org.netbeans.tax; 20 21 import java.util.Collection ; 22 import java.util.List ; 23 import java.util.Iterator ; 24 import java.util.ListIterator ; 25 import java.util.LinkedList ; 26 27 import java.beans.PropertyChangeListener ; 28 29 import org.netbeans.tax.event.TreeEventManager; 30 import org.netbeans.tax.event.TreeNodeContentEventModel; 31 32 37 public class TreeObjectList extends TreeObject implements TreeNodeContentEventModel, List { 38 41 42 public static final String PROP_CONTENT_INSERT = "contentInsert"; 44 45 public static final String PROP_CONTENT_REMOVE = "contentRemove"; 47 48 public static final String PROP_CONTENT_ORDER = "contentOrder"; 50 51 52 private ContentManager contentManager; 53 54 55 private List list; 56 57 58 62 65 protected TreeObjectList (ContentManager contentManager) { 66 super (); 67 68 this.contentManager = contentManager; 69 this.list = new LinkedList (); 70 } 71 72 73 protected TreeObjectList (TreeObjectList objectList) { 74 super (objectList); 75 76 this.contentManager = null; 77 78 this.list = new LinkedList (); 79 Iterator it = objectList.iterator (); 80 81 boolean wasReadOnly = this.isReadOnly (); 82 if ( wasReadOnly ) { 83 this.setReadOnly (false); 84 } 85 while ( it.hasNext () ) { 86 this.add (((TreeObject)it.next ()).clone ()); 87 } 88 if ( wasReadOnly ) { 89 this.setReadOnly (true); 90 } 91 } 92 93 94 98 100 public Object clone () { 101 return new TreeObjectList (this); 102 } 103 104 106 public boolean equals (Object object, boolean deep) { 107 if (!!! super.equals (object, deep)) 108 return false; 109 110 TreeObjectList peer = (TreeObjectList) object; 111 if ( this.list.size () != peer.list.size () ) 112 return false; 113 114 Iterator thisIt = this.list.iterator (); 115 Iterator peerIt = peer.list.iterator (); 116 while ( thisIt.hasNext () ) { 117 Object thisNext = thisIt.next (); 118 Object peerNext = peerIt.next (); 119 if (!!! Util.equals (thisNext, peerNext)) 120 return false; 121 } 122 123 return true; 124 } 125 126 130 public void merge (TreeObject treeObject) throws CannotMergeException { 131 super.merge (treeObject); 132 133 TreeObjectList peer = (TreeObjectList) treeObject; 134 135 141 144 boolean wasReadOnly = this.isReadOnly (); 145 if ( wasReadOnly ) { 146 this.setReadOnly (false); 147 } 148 149 TreeObject[] backupArray = (TreeObject[]) list.toArray (new TreeObject[0]); 150 list.clear (); 152 short policy = TreeEventManager.FIRE_LATER; 153 TreeEventManager manager = getEventManager (); 154 if (manager != null) { 155 policy = manager.getFirePolicy (); 156 manager.setFirePolicy (TreeEventManager.FIRE_LATER); 157 } 158 159 161 boolean reordered = true; 162 int permutation[] = null; 163 int originalIndex = 0; 164 165 if (backupArray.length == peer.list.size ()) { 166 permutation = new int[backupArray.length]; 167 } else { 168 reordered = false; 169 } 170 171 173 for (Iterator it = peer.list.iterator (); it.hasNext (); originalIndex++) { 174 TreeObject peerNode = (TreeObject) it.next (); 175 TreeObject suitableNode = null; 176 177 180 int suitableIndex = findMergeCandidate (peerNode, backupArray); 181 if (suitableIndex >= 0) { 182 suitableNode = backupArray[suitableIndex]; 183 backupArray[suitableIndex] = null; 184 } 185 186 189 if (suitableNode != null) { 191 suitableNode.merge (peerNode); 192 addNoFire (suitableNode); if (permutation != null) permutation[originalIndex] = suitableIndex; 194 195 } else { 196 197 suitableNode = peerNode; 198 add (suitableNode); 199 reordered = false; 200 201 } 202 203 } 204 205 207 if (reordered) { 208 209 211 reordered = false; 212 213 for (int i = 0; i<permutation.length; i++) { 214 if (permutation[i] != i) { 215 reordered = true; 216 break; 217 } 218 } 219 if (reordered) firePropertyOrder (permutation); 220 221 } else { 222 223 225 for (int i = 0; i<backupArray.length; i++) { 226 if (backupArray[i] == null) 227 continue; 228 contentManagerObjectRemoved (backupArray[i]); 229 firePropertyRemove (backupArray[i]); 230 } 231 } 232 233 if ( wasReadOnly ) { 234 this.setReadOnly (true); 235 } 236 237 if (manager != null) 238 manager.setFirePolicy (policy); 239 240 } 241 242 243 249 protected int findMergeCandidate (final TreeObject original, final TreeObject[] candidates) { 250 251 253 255 for (int i = 0; i<candidates.length; i++) { 256 TreeObject candidate = candidates[i]; 257 if (candidate == null) continue; 258 259 if (original.getClass ().equals (candidate.getClass ())) { 261 return i; 262 } 263 } 264 265 return -1; 266 } 267 268 269 270 274 275 277 protected void setReadOnly (boolean newReadOnly) { 278 super.setReadOnly (newReadOnly); 279 280 Iterator it = this.list.iterator (); 281 while ( it.hasNext () ) { 282 TreeObject obj = (TreeObject) it.next (); 283 obj.setReadOnly (newReadOnly); 284 } 285 } 286 287 288 292 294 public final boolean isInContext () { 295 return true; } 297 298 300 public final void removeFromContext () throws ReadOnlyException { 301 if ( isInContext () ) { 302 this.clear (); } 304 } 305 306 307 311 313 public final ContentManager getContentManager () { 314 return contentManager; 315 } 316 317 323 324 326 public final boolean isAssignableObject (Object obj) { 327 try { 328 getContentManager ().checkAssignableObject (obj); 329 return true; 330 } catch (ClassCastException exc) { 331 return false; 332 } 333 } 334 335 339 public final void reorder (int[] perm) throws ReadOnlyException, InvalidArgumentException { 340 if (equals (perm)) { 344 return; 345 } 346 checkReadOnly (); 347 checkReorder (perm); 348 349 List newList = new LinkedList (); 350 int len = size (); 351 int[] newPerm = new int [len]; 352 for (int i = 0; i < len; i++) { 353 newPerm[perm[i]] = i; 354 } 355 for (int i = 0; i < len; i++) { 356 newList.add (list.get (newPerm[i])); 357 } 358 list = newList; 359 360 contentManagerOrderChanged (perm); 361 firePropertyOrder (perm); 362 } 363 364 366 protected final void checkReorder (int[] perm) throws InvalidArgumentException { 367 if (perm == null) { 368 throw new InvalidArgumentException 369 (Util.THIS.getString ("EXC_invalid_reorder_permutation"), 370 new NullPointerException ()); 371 } 372 if (perm.length != size ()) { 373 throw new InvalidArgumentException 374 (perm.length + " != " + size (), Util.THIS.getString ("EXC_invalid_reorder_permutation")); } 376 } 377 378 379 protected final boolean equals (int[] perm) { 380 for (int i = 0; i < perm.length; i++) { 381 if (perm[i] != i) 382 return false; 383 } 384 return true; 385 } 386 387 391 public final void switchObjects (int fromIndex, int toIndex) throws ReadOnlyException, InvalidArgumentException { 392 int len = size (); 393 int[] perm = new int [len]; 394 395 for (int i = 0; i < perm.length; i++) { 396 perm[i] = i; 397 } 398 perm[fromIndex] = toIndex; 399 perm[toIndex] = fromIndex; 400 401 reorder (perm); 402 } 403 404 406 protected final void checkUnsupportedOperation () throws TreeUnsupportedOperationException { 407 try { 408 checkReadOnly (); 409 } catch (TreeException exc) { 410 throw new TreeUnsupportedOperationException (exc); 411 } 412 } 413 414 415 419 421 public final void clear () { 422 checkUnsupportedOperation (); 423 424 Iterator it = (new LinkedList (list)).iterator (); while (it.hasNext ()) { 427 Object obj = it.next (); 428 remove (obj); 429 } 430 } 431 432 434 public final boolean removeAll (Collection collection) throws UnsupportedOperationException { 435 checkUnsupportedOperation (); 436 437 throw new UnsupportedOperationException (); 439 } 440 441 443 public final Object get (int index) { 444 return list.get (index); 445 } 446 447 449 public final int hashCode () { 450 return list.hashCode (); 451 } 452 453 455 public final int size () { 456 return list.size (); 457 } 458 459 461 public final boolean retainAll (Collection collection) throws UnsupportedOperationException { 462 checkUnsupportedOperation (); 463 464 throw new UnsupportedOperationException (); 466 } 467 468 470 protected boolean removeImpl (Object obj) { 471 return list.remove (obj); 472 } 473 474 476 public final boolean remove (Object obj) { 477 checkUnsupportedOperation (); 478 479 boolean removed = removeImpl (obj); 480 if (removed) { 481 contentManagerObjectRemoved ((TreeObject)obj); 482 firePropertyRemove ((TreeObject)obj); 483 } 484 return removed; 485 } 486 487 489 public final int indexOf (Object obj) { 490 return list.indexOf (obj); 491 } 492 493 495 public final boolean contains (Object obj) { 496 return list.contains (obj); 497 } 498 499 501 public final int lastIndexOf (Object obj) { 502 return list.lastIndexOf (obj); 503 } 504 505 507 protected Object setImpl (int index, Object obj) { 508 return list.set (index, obj); 509 } 510 511 513 public final Object set (int index, Object obj) { 514 checkUnsupportedOperation (); 515 contentManagerCheckAssignableObject (obj); 516 517 Object oldObj = setImpl (index, obj); 518 contentManagerObjectRemoved ((TreeObject)oldObj); 520 firePropertyRemove ((TreeObject)oldObj); 521 contentManagerObjectInserted ((TreeObject)obj); 523 firePropertyInsert ((TreeObject)obj); 524 525 return oldObj; 526 } 527 528 530 public final ListIterator listIterator (int index) throws UnsupportedOperationException { 531 throw new UnsupportedOperationException (); 533 } 534 535 537 public final boolean containsAll (Collection collection) { 538 return list.containsAll (collection); 539 } 540 541 543 public final Iterator iterator () { 544 return (new LinkedList (list)).iterator (); } 546 547 549 public final boolean addAll (Collection collection) { 550 checkUnsupportedOperation (); 551 552 boolean changed = false; 553 Iterator it = collection.iterator (); 554 while ( it.hasNext () ) { 555 this.add (it.next ()); 556 changed = true; 557 } 558 return changed; 559 } 560 561 563 protected Object removeImpl (int index) { 564 return list.remove (index); 565 } 566 567 569 public final Object remove (int index) { 570 checkUnsupportedOperation (); 571 572 Object oldObj = removeImpl (index); 573 if (oldObj != null) { 574 contentManagerObjectRemoved ((TreeObject)oldObj); 575 firePropertyRemove ((TreeObject)oldObj); 576 } 577 return (oldObj); 578 } 579 580 582 public final boolean isEmpty () { 583 return list.isEmpty (); 584 } 585 586 588 protected void addImpl (int index, Object obj) { 589 list.add (index, obj); 590 } 591 592 594 public final void add (int index, Object obj) { 595 checkUnsupportedOperation (); 596 contentManagerCheckAssignableObject (obj); 597 598 addImpl (index, obj); 599 contentManagerObjectInserted ((TreeObject)obj); 600 firePropertyInsert ((TreeObject)obj); 601 } 602 603 605 public final boolean equals (Object obj) { 606 if (!!! ( obj instanceof TreeObjectList )) 607 return false; 608 return list.equals (((TreeObjectList)obj).list); 609 } 610 611 613 public final boolean addAll (int index, Collection collection) throws UnsupportedOperationException { 614 checkUnsupportedOperation (); 615 616 throw new UnsupportedOperationException (); 618 } 619 620 622 protected boolean addImpl (Object obj) { 623 return list.add (obj); 624 } 625 626 631 private boolean addNoFire (Object obj) { 632 checkUnsupportedOperation (); 633 contentManagerCheckAssignableObject (obj); 634 635 return addImpl (obj); 636 } 637 638 640 public final boolean add (Object obj) { 641 boolean added = addNoFire (obj); 642 if ( added ) { 643 contentManagerObjectInserted ((TreeObject)obj); 644 firePropertyInsert ((TreeObject)obj); 645 } 646 return added; 647 } 648 649 651 public final Object [] toArray (Object [] array) { 652 return list.toArray (array); 653 } 654 655 657 public final Object [] toArray () { 658 return list.toArray (); 659 } 660 661 663 public final ListIterator listIterator () throws UnsupportedOperationException { 664 throw new UnsupportedOperationException (); 666 } 667 668 670 public final List subList (int fromIndex, int toIndex) throws UnsupportedOperationException { 671 throw new UnsupportedOperationException (); 673 } 674 675 676 680 682 public String toString () { 683 return list.toString (); 684 } 685 686 687 691 694 public final TreeEventManager getEventManager () { 695 TreeNode ownerNode = contentManagerGetOwnerNode (); 696 697 if (ownerNode == null) 698 return null; 699 700 return ownerNode.getEventManager (); 701 } 702 703 706 public final void addContentChangeListener (PropertyChangeListener listener) { 707 getEventChangeSupport ().addPropertyChangeListener (PROP_CONTENT_INSERT, listener); 708 getEventChangeSupport ().addPropertyChangeListener (PROP_CONTENT_REMOVE, listener); 709 getEventChangeSupport ().addPropertyChangeListener (PROP_CONTENT_ORDER, listener); 710 } 711 712 715 public final void removeContentChangeListener (PropertyChangeListener listener) { 716 getEventChangeSupport ().removePropertyChangeListener (PROP_CONTENT_INSERT, listener); 717 getEventChangeSupport ().removePropertyChangeListener (PROP_CONTENT_REMOVE, listener); 718 getEventChangeSupport ().removePropertyChangeListener (PROP_CONTENT_ORDER, listener); 719 } 720 721 723 public final boolean hasContentChangeListeners () { 724 return getEventChangeSupport ().hasPropertyChangeListeners (PROP_CONTENT_INSERT) 725 || getEventChangeSupport ().hasPropertyChangeListeners (PROP_CONTENT_REMOVE) 726 || getEventChangeSupport ().hasPropertyChangeListeners (PROP_CONTENT_ORDER); 727 } 728 729 731 public final void firePropertyInsert (TreeObject newNode) { 732 firePropertyChange (getEventChangeSupport ().createEvent (PROP_CONTENT_INSERT, null, newNode)); 733 } 734 735 737 public final void firePropertyRemove (TreeObject oldNode) { 738 firePropertyChange (getEventChangeSupport ().createEvent (PROP_CONTENT_REMOVE, oldNode, null)); 739 } 740 741 743 public final void firePropertyOrder (int [] permutation) { 744 firePropertyChange (getEventChangeSupport ().createEvent (PROP_CONTENT_ORDER, null, permutation)); 745 } 746 747 748 752 753 755 protected final TreeNode contentManagerGetOwnerNode () { 756 if (contentManager != null) { 757 return contentManager.getOwnerNode (); 758 } else { 759 return null; 760 } 761 } 762 763 765 protected final void contentManagerCheckAssignableObject (Object object) { 766 if (contentManager != null) { 767 contentManager.checkAssignableObject (object); 768 } 769 } 770 771 773 protected final void contentManagerObjectInserted (TreeObject treeObject) { 774 if (contentManager != null) { 775 contentManager.objectInserted (treeObject); 776 } 777 } 778 779 781 protected final void contentManagerObjectRemoved (TreeObject treeObject) { 782 if (contentManager != null) { 783 contentManager.objectRemoved (treeObject); 784 } 785 } 786 787 789 protected final void contentManagerOrderChanged (int[] permutation) { 790 if (contentManager != null) { 791 contentManager.orderChanged (permutation); 792 } 793 } 794 795 796 799 public static abstract class ContentManager { 800 801 804 public abstract TreeNode getOwnerNode (); 805 806 808 public void checkAssignableObject (Object obj) throws ClassCastException { 809 if (!!! (obj instanceof TreeObject)) { 810 String msg = Util.THIS.getString ("EXC_invalid_instance_of_TreeObject"); throw new ClassCastException (msg); 812 } 813 } 814 815 817 protected final void checkAssignableClass (Class cls, Object obj) throws ClassCastException { 818 if (!!! cls.isInstance (obj)) { 819 String msg = Util.THIS.getString ("EXC_is_not_assignable_to", cls.getName ()); throw new ClassCastException (msg); 821 } 822 } 823 824 827 public abstract void objectInserted (TreeObject obj); 828 829 832 public abstract void objectRemoved (TreeObject obj); 833 834 835 public abstract void orderChanged (int[] permutation); 836 837 } 839 } 840 | Popular Tags |