KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > src > nodes > ClassChildren


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
20 package org.openide.src.nodes;
21
22 import java.beans.PropertyChangeListener JavaDoc;
23 import java.beans.PropertyChangeEvent JavaDoc;
24 import java.util.*;
25
26 import org.openide.nodes.Children;
27 import org.openide.nodes.Node;
28 import org.openide.cookies.FilterCookie;
29 import org.openide.util.WeakListeners;
30 import org.openide.src.*;
31
32 /** Normal implementation of children list for a class element node.
33 * Semantics are similar to those of {@link SourceChildren}.
34 * @author Dafe Simonek, Jan Jancura
35 */

36 public class ClassChildren extends Children.Keys implements FilterCookie {
37
38     /** Support for PACKAGE modifier */
39     private static int PPP_MASK = SourceElementFilter.PUBLIC +
40             SourceElementFilter.PRIVATE +
41             SourceElementFilter.PROTECTED;
42     /** Converts property names to filter. */
43     protected static HashMap propToFilter;
44
45     /** For sorting groups of elements. */
46     private static Comparator comparator = new Comparator () {
47                 public int compare (Object JavaDoc o1, Object JavaDoc o2) {
48                     if (o1 instanceof MemberElement)
49                         if (o2 instanceof MemberElement)
50                             return ((MemberElement) o1).getName ().getName ().compareToIgnoreCase (
51                                        ((MemberElement) o2).getName ().getName ()
52                                    );
53                         else
54                             return -1;
55                     else
56                         if (o2 instanceof MemberElement)
57                             return 1;
58                         else
59                             return 0;
60                 }
61             };
62
63     static {
64         propToFilter = new HashMap ();
65         propToFilter.put (ElementProperties.PROP_CLASSES, new Integer JavaDoc (ClassElementFilter.CLASS | ClassElementFilter.INTERFACE));
66         propToFilter.put (ElementProperties.PROP_METHODS, new Integer JavaDoc (ClassElementFilter.METHOD));
67         propToFilter.put (ElementProperties.PROP_FIELDS, new Integer JavaDoc (ClassElementFilter.FIELD));
68         propToFilter.put (ElementProperties.PROP_CONSTRUCTORS, new Integer JavaDoc (ClassElementFilter.CONSTRUCTOR));
69         propToFilter.put (ElementProperties.PROP_INITIALIZERS, new Integer JavaDoc (ClassElementFilter.CONSTRUCTOR));
70     }
71
72     /** The class element whose subelements are represented. */
73     protected ClassElement element;
74     /** Filter for elements, or <code>null</code> to disable. */
75     protected ClassElementFilter filter;
76     /** Factory for creating new child nodes. */
77     protected ElementNodeFactory factory;
78     /** Weak listener to the element and filter changes */
79     private PropertyChangeListener JavaDoc wPropL;
80     /** Listener to the element and filter changes. This reference must
81     * be kept to prevent the listener from finalizing when we are alive */

82     private ElementListener propL;
83     /** Central memory of mankind is used when some elements are changed */
84     protected Collection[] cpl;
85     /** Flag saying whether we have our nodes initialized */
86     private boolean nodesInited = false;
87
88
89     // init ................................................................................
90

91     /** Create class children with the default factory.
92     * The children are initially unfiltered.
93     * @param element attached class element (non-<code>null</code>)
94     */

95     public ClassChildren (final ClassElement element) {
96         this(DefaultFactory.READ_WRITE, element);
97     }
98
99     /** Create class children.
100     * The children are initially unfiltered.
101     * @param factory the factory to use to create new children
102     * @param element attached class element (non-<code>null</code>)
103     */

104     public ClassChildren (final ElementNodeFactory factory,
105                           final ClassElement element) {
106         super();
107         this.element = element;
108         this.factory = factory;
109         this.filter = null;
110     }
111
112
113     /********** Implementation of filter cookie **********/
114
115     /* @return The class of currently asociated filter or null
116     * if no filter is asociated with these children.
117     */

118     public Class JavaDoc getFilterClass () {
119         return ClassElementFilter.class;
120     }
121
122     /* @return The filter currently asociated with these children
123     */

124     public Object JavaDoc getFilter () {
125         return filter;
126     }
127
128     /* Sets new filter for these children.
129     * @param filter New filter. Null == disable filtering.
130     */

131     public void setFilter (final Object JavaDoc filter) {
132         if (!(filter instanceof ClassElementFilter))
133             throw new IllegalArgumentException JavaDoc();
134
135         this.filter = (ClassElementFilter)filter;
136         // change element nodes according to the new filter
137
if (nodesInited)
138             refreshAllKeys ();
139     }
140
141
142     // Children implementation ..............................................................
143

144     /* Overrides initNodes to run the preparation task of the
145     * source element, call refreshKeys and start to
146     * listen to the changes in the element too. */

147     protected void addNotify () {
148         // listen to the changes in the class element
149
if (wPropL == null) {
150             propL = new ElementListener(this);
151             wPropL = WeakListeners.propertyChange (propL, element);
152         }
153         refreshAllKeys ();
154         element.addPropertyChangeListener (wPropL);
155         nodesInited = true;
156     }
157
158     protected void removeNotify () {
159         setKeys (java.util.Collections.EMPTY_SET);
160         nodesInited = false;
161     }
162     
163     private Node hookNodeName(Node n) {
164         MemberElement el = (MemberElement)n.getCookie(MemberElement.class);
165         if (el != null)
166             el.addPropertyChangeListener(propL);
167         return n;
168     }
169
170     /* Creates node for given key.
171     * The node is created using node factory.
172     */

173     protected Node[] createNodes (final Object JavaDoc key) {
174         if (key instanceof MethodElement) {
175             return new Node[] { hookNodeName(factory.createMethodNode((MethodElement)key)) };
176         }
177         if (key instanceof FieldElement) {
178             return new Node[] { hookNodeName(factory.createFieldNode((FieldElement)key)) };
179         }
180         if (key instanceof ConstructorElement) {
181             return new Node[] { hookNodeName(factory.createConstructorNode((ConstructorElement)key)) };
182         }
183         if (key instanceof ClassElement) {
184             return new Node[] { hookNodeName(factory.createClassNode((ClassElement)key)) };
185         }
186         if (key instanceof InitializerElement) {
187             return new Node[] { hookNodeName(factory.createInitializerNode((InitializerElement)key)) };
188         }
189         // ?? unknown type
190
return new Node[0];
191     }
192
193
194     /************** utility methods ************/
195
196     /** Updates all the keys (elements) according to the current filter &
197     * ordering.
198     */

199     protected void refreshAllKeys () {
200         cpl = new Collection [getOrder ().length];
201         refreshKeys (ClassElementFilter.ALL);
202     }
203
204     /** Updates all the keys with given filter.
205     */

206     protected void refreshKeys (int filter) {
207         int[] order = getOrder ();
208         LinkedList keys = new LinkedList();
209         // build ordered and filtered keys for the subelements
210
for (int i = 0; i < order.length; i++) {
211             if (((order[i] & filter) != 0) || (cpl [i] == null))
212                 keys.addAll (cpl [i] = getKeysOfType (order[i]));
213             else
214                 keys.addAll (cpl [i]);
215         }
216         // set new keys
217
ElementListener l = propL;
218         if (l != null)
219             l.updateElements(keys);
220         setKeys(keys);
221     }
222
223     /** Filters and returns the keys of specified type.
224     */

225     protected Collection getKeysOfType (final int elementType) {
226         LinkedList keys = new LinkedList();
227         if ((elementType & ClassElementFilter.EXTENDS) != 0) {
228             keys.add (element.getSuperclass ());
229         }
230         if ((elementType & ClassElementFilter.IMPLEMENTS) != 0) {
231             keys.addAll (Arrays.asList (element.getInterfaces ()));
232         }
233         if ((elementType & ClassElementFilter.FIELD) != 0) {
234             filterModifiers (element.getFields (), keys);
235         }
236         if ((elementType & ClassElementFilter.CONSTRUCTOR) != 0) {
237             filterModifiers (element.getConstructors (), keys);
238             keys.addAll (Arrays.asList (element.getInitializers ()));
239         }
240         if ((elementType & ClassElementFilter.METHOD) != 0) {
241             filterModifiers (element.getMethods (), keys);
242         }
243         if ((elementType & (ClassElementFilter.CLASS + ClassElementFilter.INTERFACE)) != 0) {
244             filterClassModifiers (element.getClasses (), keys, elementType);
245         }
246         if ((filter == null) || filter.isSorted ())
247             Collections.sort (keys, comparator);
248         return keys;
249     }
250
251     /** Returns order form filter.
252     */

253     protected int[] getOrder () {
254         return (filter == null || (filter.getOrder() == null))
255                ? ClassElementFilter.DEFAULT_ORDER : filter.getOrder();
256     }
257
258     /** Returns modifier filter form filter.
259     */

260     private int getModifierFilter () {
261         if (filter == null) return ClassElementFilter.ALL_MODIFIERS;
262         return filter.getModifiers ();
263     }
264
265     /** Filters MemberElements for modifiers, and adds them to the given collection.
266     */

267     private void filterModifiers (MemberElement[] elements, Collection keys) {
268         int ff = getModifierFilter ();
269         int i, k = elements.length;
270         for (i = 0; i < k; i ++) {
271             int f = elements [i].getModifiers ();
272             if ((f & PPP_MASK) == 0) f += ClassElementFilter.PACKAGE;
273             if ((f & ff) != 0) keys.add (elements [i]);
274         }
275     }
276
277     /** Filters ClassElements for their type, and adds them to the given collection.
278     */

279     private void filterClassModifiers (ClassElement[] elements, Collection keys, int filter) {
280         int ff = getModifierFilter ();
281         int i, k = elements.length;
282         for (i = 0; i < k; i ++) {
283             int f = elements [i].getModifiers ();
284             if ((f & PPP_MASK) == 0) f += ClassElementFilter.PACKAGE;
285             if ((f & ff) == 0) continue;
286             if (elements [i].isClass ()) {
287                 if ((filter & ClassElementFilter.CLASS) != 0) keys.add (elements [i]);
288             } else
289                 if ((filter & ClassElementFilter.INTERFACE) != 0) keys.add (elements [i]);
290         }
291     }
292
293
294     // innerclasses ...........................................................................
295

296     /** The listener for listening to the property changes in the filter.
297     */

298     private static final class ElementListener extends java.lang.ref.WeakReference JavaDoc implements Runnable JavaDoc, PropertyChangeListener JavaDoc {
299         Collection elements;
300
301         ElementListener(ClassChildren cc) {
302             super(cc, org.openide.util.Utilities.activeReferenceQueue());
303         }
304
305         ClassChildren getClassChildren() {
306             Object JavaDoc o = get();
307             return (ClassChildren)o;
308         }
309
310         /** This method is called when the change of properties occurs in the element.
311         * PENDING - (for Hanz - should be implemented better, change only the
312         * keys which belong to the changed property).
313         * -> YES MY LORD! ANOTHER WISH?
314         */

315         public void propertyChange (PropertyChangeEvent JavaDoc evt) {
316             Object JavaDoc src = evt.getSource();
317             String JavaDoc propName = evt.getPropertyName();
318             int filter;
319
320             ClassChildren cc = getClassChildren();
321             if (cc == null)
322                 return;
323
324             if (src != cc.element) {
325                 if (src instanceof MemberElement &&
326                     (propName == null || ElementProperties.PROP_NAME == propName)) {
327                     if (src instanceof MethodElement)
328                         filter = ClassElementFilter.METHOD;
329                     else if (src instanceof ConstructorElement)
330                         filter = ClassElementFilter.CONSTRUCTOR;
331                     else if (src instanceof FieldElement)
332                         filter = ClassElementFilter.FIELD;
333                     else
334                         filter = ClassElementFilter.CLASS | ClassElementFilter.INTERFACE;
335                 } else
336                     return;
337             } else {
338                Integer JavaDoc i = (Integer JavaDoc) cc.propToFilter.get (propName);
339                if (i == null)
340                    return;
341                filter = i.intValue();
342             }
343             cc.refreshKeys (filter);
344         }
345
346         void updateElements(Collection c) {
347             this.elements = c;
348         }
349
350         public void run() {
351             // clean-up
352
for (Iterator it = elements.iterator(); it.hasNext(); ) {
353                 Object JavaDoc o = it.next();
354                 if (!(o instanceof Element))
355                     continue;
356                 Element el = (Element)o;
357                 el.removePropertyChangeListener(this);
358             }
359         }
360     } // end of ElementListener inner class
361
}
362
Popular Tags