KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > tax > TreeObjectList


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.tax;
20
21 import java.util.Collection JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.ListIterator JavaDoc;
25 import java.util.LinkedList JavaDoc;
26
27 import java.beans.PropertyChangeListener JavaDoc;
28
29 import org.netbeans.tax.event.TreeEventManager;
30 import org.netbeans.tax.event.TreeNodeContentEventModel;
31
32 /**
33  *
34  * @author Libor Kramolis
35  * @version 0.1
36  */

37 public class TreeObjectList extends TreeObject implements TreeNodeContentEventModel, List JavaDoc {
38     // toDo:
39
// + set inserted object readOnly value as object list has
40

41     /** Name of property for insert node to node content. */
42     public static final String JavaDoc PROP_CONTENT_INSERT = "contentInsert"; // NOI18N
43

44     /** Name of property for remove node from node content. */
45     public static final String JavaDoc PROP_CONTENT_REMOVE = "contentRemove"; // NOI18N
46

47     /** Name of property for change order in node content. */
48     public static final String JavaDoc PROP_CONTENT_ORDER = "contentOrder"; // NOI18N
49

50     
51     /** */
52     private ContentManager contentManager;
53     
54     /** */
55     private List JavaDoc list;
56     
57     
58     //
59
// init
60
//
61

62     /**
63      * Creates new TreeObjectList.
64      */

65     protected TreeObjectList (ContentManager contentManager) {
66         super ();
67         
68         this.contentManager = contentManager;
69         this.list = new LinkedList JavaDoc ();
70     }
71     
72     /** Creates new TreeObjectList -- copy constructor. */
73     protected TreeObjectList (TreeObjectList objectList) {
74         super (objectList);
75         
76         this.contentManager = null;
77         
78         this.list = new LinkedList JavaDoc ();
79         Iterator JavaDoc 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     //
95
// from TreeObject
96
//
97

98     /**
99      */

100     public Object JavaDoc clone () {
101         return new TreeObjectList (this);
102     }
103     
104     /**
105      */

106     public boolean equals (Object JavaDoc 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 JavaDoc thisIt = this.list.iterator ();
115         Iterator JavaDoc peerIt = peer.list.iterator ();
116         while ( thisIt.hasNext () ) {
117             Object JavaDoc thisNext = thisIt.next ();
118             Object JavaDoc peerNext = peerIt.next ();
119             if (!!! Util.equals (thisNext, peerNext))
120                 return false;
121         }
122         
123         return true;
124     }
125     
126     /*
127      * Merge list content by merging instances using findMergeCandidate().
128      * Let list's ContentManagers update structural links.
129      */

130     public void merge (TreeObject treeObject) throws CannotMergeException {
131         super.merge (treeObject);
132         
133         TreeObjectList peer = (TreeObjectList) treeObject;
134         
135         // merge nodeList;
136
// try to reuse old instances by type in FIFO order
137
// note that in tree editor (and anyone manipulating this structure directly)
138
// it is ok so no explorer node collapsing would occure
139
// see children package from related details
140

141         // I think no optimalization can be performend since
142
// there is not uniq id of element
143

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 (); //do not use content manager, do not fire
151

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         // if the size is the same => order may be changed
160

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         // MERGE
172

173         for (Iterator JavaDoc it = peer.list.iterator (); it.hasNext (); originalIndex++) {
174             TreeObject peerNode = (TreeObject) it.next ();
175             TreeObject suitableNode = null;
176             
177             // search backup array for suitable element and place it in suitableNode
178
// then mark the backup array entry by null as used
179

180             int suitableIndex = findMergeCandidate (peerNode, backupArray);
181             if (suitableIndex >= 0) {
182                 suitableNode = backupArray[suitableIndex];
183                 backupArray[suitableIndex] = null;
184             }
185             
186             // add to current list and let list's ContentManagers
187
// update their structural references
188

189             if (suitableNode != null) { // if exist merge it
190

191                 suitableNode.merge (peerNode);
192                 addNoFire (suitableNode); // we were there before clear()
193
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         // cache events to be fired
206

207         if (reordered) {
208             
209             // check the permutation, ignore identical one
210

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             // fire removal events for rest of backup array
224

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     /**
244      * Defines algorithm used for searching for must suitable merge peer.
245      * @param original we search suitable candidate for this
246      * @param candidates array of candidates and nulls
247      * @return index of suitable candidate or -1
248      */

249     protected int findMergeCandidate (final TreeObject original, final TreeObject[] candidates) {
250         
251         // suitable if first member of the same class
252

253         // System.err.println("Looking for peer candidate:" + System.identityHashCode(original) + " " + original.getClass()); // NOI18N
254

255         for (int i = 0; i<candidates.length; i++) {
256             TreeObject candidate = candidates[i];
257             if (candidate == null) continue;
258             
259             // System.err.println("Inspecting: " + System.identityHashCode(candidate) + " " + candidate.getClass()); // NOI18N
260
if (original.getClass ().equals (candidate.getClass ())) {
261                 return i;
262             }
263         }
264         
265         return -1;
266     }
267     
268     
269     
270     //
271
// read only
272
//
273

274     
275     /**
276      */

277     protected void setReadOnly (boolean newReadOnly) {
278         super.setReadOnly (newReadOnly);
279         
280         Iterator JavaDoc it = this.list.iterator ();
281         while ( it.hasNext () ) {
282             TreeObject obj = (TreeObject) it.next ();
283             obj.setReadOnly (newReadOnly);
284         }
285     }
286     
287     
288     //
289
// context
290
//
291

292     /**
293      */

294     public final boolean isInContext () {
295         return true; //???
296
}
297     
298     /**
299      */

300     public final void removeFromContext () throws ReadOnlyException {
301         if ( isInContext () ) {
302             this.clear (); //???
303
}
304     }
305     
306     
307     //
308
// itself
309
//
310

311     /**
312      */

313     public final ContentManager getContentManager () {
314         return contentManager;
315     }
316     
317     // /**
318
// */
319
// protected final void setContentManager (ContentManager newContentManager) {
320
// this.contentManager = newContentManager;
321
// }
322

323     
324     /**
325      */

326     public final boolean isAssignableObject (Object JavaDoc obj) {
327         try {
328             getContentManager ().checkAssignableObject (obj);
329             return true;
330         } catch (ClassCastException JavaDoc exc) {
331             return false;
332         }
333     }
334     
335     /**
336      * @throws ReadOnlyException
337      * @throws InvalidArgumentException
338      */

339     public final void reorder (int[] perm) throws ReadOnlyException, InvalidArgumentException {
340         //
341
// check new value
342
//
343
if (equals (perm)) {
344             return;
345         }
346         checkReadOnly ();
347         checkReorder (perm);
348         
349         List JavaDoc newList = new LinkedList JavaDoc ();
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     /**
365      */

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 JavaDoc ());
371         }
372         if (perm.length != size ()) {
373             throw new InvalidArgumentException
374             (perm.length + " != " + size (), Util.THIS.getString ("EXC_invalid_reorder_permutation")); // NOI18N
375
}
376     }
377     
378     /** @return true if <code>perm</code> is identical permutaion. */
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     /**
388      * @throws ReadOnlyException
389      * @throws InvalidArgumentException
390      */

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     /**
405      */

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     //
416
// java.util.List
417
//
418

419     /**
420      */

421     public final void clear () {
422         checkUnsupportedOperation ();
423         
424         // list.clear();
425
Iterator JavaDoc it = (new LinkedList JavaDoc (list)).iterator (); // new LinkedList => fixed ConcurentModificationException
426
while (it.hasNext ()) {
427             Object JavaDoc obj = it.next ();
428             remove (obj);
429         }
430     }
431     
432     /**
433      */

434     public final boolean removeAll (Collection JavaDoc collection) throws UnsupportedOperationException JavaDoc {
435         checkUnsupportedOperation ();
436         
437         // return list.removeAll (collection);
438
throw new UnsupportedOperationException JavaDoc ();
439     }
440     
441     /**
442      */

443     public final Object JavaDoc get (int index) {
444         return list.get (index);
445     }
446     
447     /**
448      */

449     public final int hashCode () {
450         return list.hashCode ();
451     }
452     
453     /**
454      */

455     public final int size () {
456         return list.size ();
457     }
458     
459     /**
460      */

461     public final boolean retainAll (Collection JavaDoc collection) throws UnsupportedOperationException JavaDoc {
462         checkUnsupportedOperation ();
463         
464         // return list.retainAll (collection);
465
throw new UnsupportedOperationException JavaDoc ();
466     }
467     
468     /**
469      */

470     protected boolean removeImpl (Object JavaDoc obj) {
471         return list.remove (obj);
472     }
473     
474     /**
475      */

476     public final boolean remove (Object JavaDoc 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     /**
488      */

489     public final int indexOf (Object JavaDoc obj) {
490         return list.indexOf (obj);
491     }
492     
493     /**
494      */

495     public final boolean contains (Object JavaDoc obj) {
496         return list.contains (obj);
497     }
498     
499     /**
500      */

501     public final int lastIndexOf (Object JavaDoc obj) {
502         return list.lastIndexOf (obj);
503     }
504     
505     /**
506      */

507     protected Object JavaDoc setImpl (int index, Object JavaDoc obj) {
508         return list.set (index, obj);
509     }
510     
511     /**
512      */

513     public final Object JavaDoc set (int index, Object JavaDoc obj) {
514         checkUnsupportedOperation ();
515         contentManagerCheckAssignableObject (obj);
516         
517         Object JavaDoc oldObj = setImpl (index, obj);
518         // if (obj != oldObj) {
519
contentManagerObjectRemoved ((TreeObject)oldObj);
520         firePropertyRemove ((TreeObject)oldObj);
521         // }
522
contentManagerObjectInserted ((TreeObject)obj);
523         firePropertyInsert ((TreeObject)obj);
524         
525         return oldObj;
526     }
527     
528     /**
529      */

530     public final ListIterator JavaDoc listIterator (int index) throws UnsupportedOperationException JavaDoc {
531         // return list.listIterator (index);
532
throw new UnsupportedOperationException JavaDoc ();
533     }
534     
535     /**
536      */

537     public final boolean containsAll (Collection JavaDoc collection) {
538         return list.containsAll (collection);
539     }
540     
541     /**
542      */

543     public final Iterator JavaDoc iterator () {
544         return (new LinkedList JavaDoc (list)).iterator (); //!!! TEMPORARY : fixed ConcurrentModificationException but iterator is not active
545
}
546     
547     /**
548      */

549     public final boolean addAll (Collection JavaDoc collection) {
550         checkUnsupportedOperation ();
551         
552         boolean changed = false;
553         Iterator JavaDoc it = collection.iterator ();
554         while ( it.hasNext () ) {
555             this.add (it.next ());
556             changed = true;
557         }
558         return changed;
559     }
560     
561     /**
562      */

563     protected Object JavaDoc removeImpl (int index) {
564         return list.remove (index);
565     }
566     
567     /**
568      */

569     public final Object JavaDoc remove (int index) {
570         checkUnsupportedOperation ();
571         
572         Object JavaDoc oldObj = removeImpl (index);
573         if (oldObj != null) {
574             contentManagerObjectRemoved ((TreeObject)oldObj);
575             firePropertyRemove ((TreeObject)oldObj);
576         }
577         return (oldObj);
578     }
579     
580     /**
581      */

582     public final boolean isEmpty () {
583         return list.isEmpty ();
584     }
585     
586     /**
587      */

588     protected void addImpl (int index, Object JavaDoc obj) {
589         list.add (index, obj);
590     }
591     
592     /**
593      */

594     public final void add (int index, Object JavaDoc obj) {
595         checkUnsupportedOperation ();
596         contentManagerCheckAssignableObject (obj);
597         
598         addImpl (index, obj);
599         contentManagerObjectInserted ((TreeObject)obj);
600         firePropertyInsert ((TreeObject)obj);
601     }
602     
603     /**
604      */

605     public final boolean equals (Object JavaDoc obj) {
606         if (!!! ( obj instanceof TreeObjectList ))
607             return false;
608         return list.equals (((TreeObjectList)obj).list);
609     }
610     
611     /**
612      */

613     public final boolean addAll (int index, Collection JavaDoc collection) throws UnsupportedOperationException JavaDoc {
614         checkUnsupportedOperation ();
615         
616         // return list.addAll (index, collection);
617
throw new UnsupportedOperationException JavaDoc ();
618     }
619     
620     /**
621      */

622     protected boolean addImpl (Object JavaDoc obj) {
623         return list.add (obj);
624     }
625     
626     /*
627      * Add to list, Do NOT notify ContentManager and do not fire
628      * the added object already was in the list.
629      * Used during merge process.
630      */

631     private boolean addNoFire (Object JavaDoc obj) {
632         checkUnsupportedOperation ();
633         contentManagerCheckAssignableObject (obj);
634         
635         return addImpl (obj);
636     }
637     
638     /**
639      */

640     public final boolean add (Object JavaDoc obj) {
641         boolean added = addNoFire (obj);
642         if ( added ) {
643             contentManagerObjectInserted ((TreeObject)obj);
644             firePropertyInsert ((TreeObject)obj);
645         }
646         return added;
647     }
648     
649     /**
650      */

651     public final Object JavaDoc[] toArray (Object JavaDoc[] array) {
652         return list.toArray (array);
653     }
654     
655     /**
656      */

657     public final Object JavaDoc[] toArray () {
658         return list.toArray ();
659     }
660     
661     /**
662      */

663     public final ListIterator JavaDoc listIterator () throws UnsupportedOperationException JavaDoc {
664         // return list.listIterator();
665
throw new UnsupportedOperationException JavaDoc ();
666     }
667     
668     /**
669      */

670     public final List JavaDoc subList (int fromIndex, int toIndex) throws UnsupportedOperationException JavaDoc {
671         // return list.subList (fromIndex, toIndex);
672
throw new UnsupportedOperationException JavaDoc ();
673     }
674     
675     
676     //
677
// toString
678
//
679

680     /**
681      */

682     public String JavaDoc toString () {
683         return list.toString ();
684     }
685     
686     
687     //
688
// event model
689
//
690

691     /** Get assigned event manager which is assigned to ownerNode.
692      * @return assigned event manager (may be null).
693      */

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     /**
704      * @param listener The listener to add.
705      */

706     public final void addContentChangeListener (PropertyChangeListener JavaDoc 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     /**
713      * @param listener The listener to remove.
714      */

715     public final void removeContentChangeListener (PropertyChangeListener JavaDoc 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     /**
722      */

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     /**
730      */

731     public final void firePropertyInsert (TreeObject newNode) {
732         firePropertyChange (getEventChangeSupport ().createEvent (PROP_CONTENT_INSERT, null, newNode));
733     }
734     
735     /**
736      */

737     public final void firePropertyRemove (TreeObject oldNode) {
738         firePropertyChange (getEventChangeSupport ().createEvent (PROP_CONTENT_REMOVE, oldNode, null));
739     }
740     
741     /**
742      */

743     public final void firePropertyOrder (int [] permutation) {
744         firePropertyChange (getEventChangeSupport ().createEvent (PROP_CONTENT_ORDER, null, permutation));
745     }
746     
747     
748     //
749
// class ContentManager
750
//
751

752     
753     /**
754      */

755     protected final TreeNode contentManagerGetOwnerNode () {
756         if (contentManager != null) {
757             return contentManager.getOwnerNode ();
758         } else {
759             return null;
760         }
761     }
762     
763     /**
764      */

765     protected final void contentManagerCheckAssignableObject (Object JavaDoc object) {
766         if (contentManager != null) {
767             contentManager.checkAssignableObject (object);
768         }
769     }
770     
771     /**
772      */

773     protected final void contentManagerObjectInserted (TreeObject treeObject) {
774         if (contentManager != null) {
775             contentManager.objectInserted (treeObject);
776         }
777     }
778     
779     /**
780      */

781     protected final void contentManagerObjectRemoved (TreeObject treeObject) {
782         if (contentManager != null) {
783             contentManager.objectRemoved (treeObject);
784         }
785     }
786     
787     /**
788      */

789     protected final void contentManagerOrderChanged (int[] permutation) {
790         if (contentManager != null) {
791             contentManager.orderChanged (permutation);
792         }
793     }
794     
795     
796     /**
797      *
798      */

799     public static abstract class ContentManager {
800         
801         /**
802          * @return reference to the particular object list owner that created us
803          */

804         public abstract TreeNode getOwnerNode ();
805         
806         /** @throws ClassCastException
807          */

808         public void checkAssignableObject (Object JavaDoc obj) throws ClassCastException JavaDoc {
809             if (!!! (obj instanceof TreeObject)) {
810                 String JavaDoc msg = Util.THIS.getString ("EXC_invalid_instance_of_TreeObject"); //,obj.getClass().getName());
811
throw new ClassCastException JavaDoc (msg);
812             }
813         }
814         
815         /** @throws ClassCastException
816          */

817         protected final void checkAssignableClass (Class JavaDoc cls, Object JavaDoc obj) throws ClassCastException JavaDoc {
818             if (!!! cls.isInstance (obj)) {
819                 String JavaDoc msg = Util.THIS.getString ("EXC_is_not_assignable_to", cls.getName ()); //,obj.getClass().getName(), cls.getName());
820
throw new ClassCastException JavaDoc (msg);
821             }
822         }
823         
824         /**
825          * Called AFTER object insertion.
826          */

827         public abstract void objectInserted (TreeObject obj);
828         
829         /**
830          * Called AFTER object removal before firing.
831          */

832         public abstract void objectRemoved (TreeObject obj);
833         
834         /** */
835         public abstract void orderChanged (int[] permutation);
836         
837     } // end: interface ContentManager
838

839 }
840
Popular Tags