KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > nodes > NodeLookup


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.nodes;
21
22 import java.util.ArrayList JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Collections JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import org.openide.util.Lookup.Template;
27 import org.openide.util.lookup.AbstractLookup;
28 import org.openide.util.lookup.AbstractLookup.Pair;
29
30 /** A lookup that represents content of a Node.getCookie and the node itself.
31  *
32  *
33  * @author Jaroslav Tulach
34  */

35 final class NodeLookup extends AbstractLookup {
36     /** See #40734 and NodeLookupTest and CookieActionIsTooSlowTest.
37      * When finding action state for FilterNode, the action might been
38      * triggered way to many times, due to initialization in beforeLookup
39      * that triggered LookupListener and PROP_COOKIE change.
40      */

41     static final ThreadLocal JavaDoc<Node> NO_COOKIE_CHANGE = new ThreadLocal JavaDoc<Node>();
42
43     /** Set of Classes that we have already queried <type>Class</type> */
44     private java.util.Collection JavaDoc<Class JavaDoc> queriedCookieClasses = new ArrayList JavaDoc<Class JavaDoc>();
45
46     /** node we are associated with
47      */

48     private Node node;
49
50     /** New flat lookup.
51      */

52     public NodeLookup(Node n) {
53         super();
54
55         this.node = n;
56         addPair(new LookupItem(n));
57     }
58
59     /** Calls into Node to find out if it has a cookie of given class.
60      * It does special tricks to make CookieSet.Entry work.
61      *
62      * @param node node to ask
63      * @param c class to query
64      * @param colleciton to put Pair into if found
65      */

66     private static void addCookie(Node node, Class JavaDoc<?> c,
67             Collection JavaDoc<AbstractLookup.Pair> collection,
68             java.util.Map JavaDoc<AbstractLookup.Pair, Class JavaDoc> fromPairToClass) {
69         Object JavaDoc res;
70         Collection JavaDoc<AbstractLookup.Pair> pairs;
71         Object JavaDoc prev = CookieSet.entryQueryMode(c);
72
73         try {
74             @SuppressWarnings JavaDoc("unchecked")
75             Class JavaDoc<? extends Node.Cookie> fake = (Class JavaDoc<? extends Node.Cookie>)c;
76             res = node.getCookie(fake);
77         } finally {
78             pairs = CookieSet.exitQueryMode(prev);
79         }
80
81         if (pairs == null) {
82             if (res == null) {
83                 return;
84             }
85
86             pairs = Collections.singleton((AbstractLookup.Pair)new LookupItem(res));
87         }
88
89         collection.addAll(pairs);
90         for (AbstractLookup.Pair p : pairs) {
91             Class JavaDoc<?> oldClazz = fromPairToClass.get(p);
92             if (oldClazz == null || c.isAssignableFrom(oldClazz)) {
93                 fromPairToClass.put(p, c);
94             }
95         }
96     }
97
98     /** Notifies subclasses that a query is about to be processed.
99      * @param template the template
100      */

101     protected final void beforeLookup(Template template) {
102         Class JavaDoc type = template.getType();
103
104         if (type == Object JavaDoc.class) {
105             // ok, this is likely query for everything
106
java.util.Set JavaDoc all;
107             Object JavaDoc prev = null;
108
109             try {
110                 prev = CookieSet.entryAllClassesMode();
111
112                 Object JavaDoc ignoreResult = node.getCookie(Node.Cookie.class);
113             } finally {
114                 all = CookieSet.exitAllClassesMode(prev);
115             }
116
117             Iterator JavaDoc it = all.iterator();
118
119             while (it.hasNext()) {
120                 Class JavaDoc c = (Class JavaDoc) it.next();
121                 updateLookupAsCookiesAreChanged(c);
122             }
123
124             // update Node.Cookie if not yet
125
if (!queriedCookieClasses.contains(Node.Cookie.class)) {
126                 updateLookupAsCookiesAreChanged(Node.Cookie.class);
127             }
128         }
129
130         if (!queriedCookieClasses.contains(type)) {
131             updateLookupAsCookiesAreChanged(type);
132         }
133     }
134
135     public void updateLookupAsCookiesAreChanged(Class JavaDoc toAdd) {
136         java.util.Collection JavaDoc<AbstractLookup.Pair> instances;
137         java.util.Map JavaDoc<AbstractLookup.Pair, Class JavaDoc> fromPairToQueryClass;
138
139         // if it is cookie change, do the rescan, try to keep order
140
synchronized (this) {
141             if (toAdd != null) {
142                 if (queriedCookieClasses.contains(toAdd)) {
143                     // if this class has already been added, go away
144
return;
145                 }
146
147                 queriedCookieClasses.add(toAdd);
148             }
149
150             instances = new java.util.LinkedHashSet JavaDoc<AbstractLookup.Pair>(queriedCookieClasses.size());
151             fromPairToQueryClass = new java.util.LinkedHashMap JavaDoc<AbstractLookup.Pair, Class JavaDoc>();
152
153             java.util.Iterator JavaDoc<Class JavaDoc> it = /* #74334 */new ArrayList JavaDoc<Class JavaDoc>(queriedCookieClasses).iterator();
154             LookupItem nodePair = new LookupItem(node);
155             instances.add(nodePair);
156             fromPairToQueryClass.put(nodePair, Node.class);
157
158             while (it.hasNext()) {
159                 Class JavaDoc c = it.next();
160                 addCookie(node, c, instances, fromPairToQueryClass);
161             }
162         }
163
164         final java.util.Map JavaDoc<AbstractLookup.Pair, Class JavaDoc> m = fromPairToQueryClass;
165
166         class Cmp implements java.util.Comparator JavaDoc<AbstractLookup.Pair> {
167             public int compare(AbstractLookup.Pair p1, AbstractLookup.Pair p2) {
168                 Class JavaDoc<?> c1 = m.get(p1);
169                 Class JavaDoc<?> c2 = m.get(p2);
170                 
171                 if (c1 == c2) {
172                     return 0;
173                 }
174
175                 if (c1.isAssignableFrom(c2)) {
176                     return -1;
177                 }
178
179                 if (c2.isAssignableFrom(c1)) {
180                     return 1;
181                 }
182
183                 if (c1.isAssignableFrom(p2.getType())) {
184                     return -1;
185                 }
186
187                 if (c2.isAssignableFrom(p1.getType())) {
188                     return 1;
189                 }
190
191                 return 0;
192             }
193         }
194
195         java.util.ArrayList JavaDoc<AbstractLookup.Pair> list = new java.util.ArrayList JavaDoc<AbstractLookup.Pair>(instances);
196         java.util.Collections.sort(list, new Cmp());
197
198         if (toAdd == null) {
199             setPairs(list);
200         } else {
201             Node prev = NO_COOKIE_CHANGE.get();
202
203             try {
204                 NO_COOKIE_CHANGE.set(node);
205
206                 // doing the setPairs under entryQueryMode guarantees that
207
// FilterNode will ignore the change
208
setPairs(list);
209             } finally {
210                 NO_COOKIE_CHANGE.set(prev);
211             }
212         }
213     }
214
215     /** Simple Pair to hold cookies and nodes */
216     private static class LookupItem extends AbstractLookup.Pair {
217         private Object JavaDoc instance;
218
219         public LookupItem(Object JavaDoc instance) {
220             this.instance = instance;
221         }
222
223         public String JavaDoc getDisplayName() {
224             return getId();
225         }
226
227         public String JavaDoc getId() {
228             return instance.toString();
229         }
230
231         public Object JavaDoc getInstance() {
232             return instance;
233         }
234
235         public Class JavaDoc getType() {
236             return instance.getClass();
237         }
238
239         public boolean equals(Object JavaDoc object) {
240             if (object instanceof LookupItem) {
241                 return instance == ((LookupItem) object).getInstance();
242             }
243
244             return false;
245         }
246
247         public int hashCode() {
248             return instance.hashCode();
249         }
250
251         protected boolean creatorOf(Object JavaDoc obj) {
252             return instance == obj;
253         }
254
255         protected boolean instanceOf(Class JavaDoc c) {
256             return c.isInstance(instance);
257         }
258     }
259      // End of LookupItem class
260
}
261
Popular Tags