KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > javacore > jmiimpl > javamodel > UsageFinder


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 /*
21  * UsageFinder.java
22  *
23  * Created on 06 January 2004, 11:44
24  */

25
26 package org.netbeans.modules.javacore.jmiimpl.javamodel;
27
28 import java.util.*;
29 import org.netbeans.jmi.javamodel.*;
30 import org.netbeans.mdr.NBMDRepositoryImpl;
31 import org.netbeans.mdr.persistence.MOFID;
32 import org.netbeans.modules.javacore.JMManager;
33 import org.netbeans.modules.javacore.internalapi.JavaMetamodel;
34 import org.netbeans.modules.javacore.internalapi.ProgressSupport;
35 import org.openide.ErrorManager;
36 import org.openide.util.Cancellable;
37
38 /**
39  *
40  * @author Jan Becicka
41  */

42 public class UsageFinder {
43     
44     private NamedElement what;
45     private ElementNavigator navigator;
46     private Collection usages;
47     private static final int MAX_COUNT = 30;
48     private Set declaringClasses;
49     private boolean overriders = false;
50     private boolean findUsages = true;
51     
52     /** Creates a new instance of UsageFinder */
53     public UsageFinder(NamedElement what) {
54         if (what instanceof ParameterizedType) {
55             this.what = convert(getRealClassDefinition((ParameterizedType) what));
56         } else {
57             this.what = convert(what);
58         }
59     }
60     
61     private static List getParameters(CallableFeature f) {
62         List params = new ArrayList();
63         for (Iterator i = f.getParameters().iterator(); i.hasNext(); params.add(convert(TypeClassImpl.getRawType(((Parameter)i.next()).getType()))));
64         return params;
65     }
66     
67     private static NamedElement convert(NamedElement what) {
68         if (what instanceof TypeParameter) {
69             return what;
70         }
71         if (what instanceof JavaClass) {
72             return convert((JavaClass) what);
73         }
74
75         NamedElement convertedElement = null;
76         
77         if (what instanceof ClassMember) {
78             ClassDefinition cls = ((ClassMember) what).getDeclaringClass();
79             if (cls instanceof JavaClass) {
80                 JavaClass clazz = (JavaClass) convert(cls);
81                 if (clazz.equals(cls)) {
82                     return what;
83                 }
84
85                 if (what instanceof Field) {
86                     convertedElement = clazz.getField(what.getName(), false);
87                 } else {
88                     if (what instanceof Method) {
89                         convertedElement = clazz.getMethod(what.getName(), getParameters((CallableFeature) what), false);
90                     } else if (what instanceof Constructor) {
91                         convertedElement = clazz.getConstructor(getParameters((CallableFeature) what), false);
92                     }
93                 }
94             }
95         }
96         return convertedElement == null ? what:convertedElement ;
97     }
98     
99     private static Type convert(Type clazz) {
100         if (clazz instanceof JavaClassImpl && ((JavaClassImpl)clazz).isTransient()) // local class
101
return clazz;
102         return JavaMetamodel.getManager().getDefaultExtent().getType().resolve(clazz.getName());
103     }
104     
105     /**
106      * specific contructor for method
107      * @param method method for search
108      * @param findUsages find usages of methods
109      * @param fromBaseClass find all occurrences including superclass
110      * @param overriders get Overriding Methods
111      */

112     public UsageFinder(CallableFeature method, boolean findUsages, boolean fromBaseClass, boolean overriders) {
113         this(method);
114         this.overriders = overriders;
115         this.findUsages = findUsages;
116         declaringClasses = new HashSet();
117         ClassDefinition clazz = method.getDeclaringClass();
118         declaringClasses.add(getRealClassDefinition(clazz));
119         List argTypes = new ArrayList();
120         for (Iterator i = method.getParameters().iterator(); i.hasNext(); argTypes.add(TypeClassImpl.getRawType(((Parameter)i.next()).getType())));
121         
122         if (fromBaseClass) {
123             LinkedList q = new LinkedList();
124             q.add(clazz);
125             HashSet visited = new HashSet();
126             while (!q.isEmpty()) {
127                 clazz = (ClassDefinition) q.removeFirst();
128                 if (visited.add(clazz)) {
129                     CallableFeature callFeature = null;
130                     if (method instanceof Method)
131                         callFeature = clazz.getMethod(method.getName(), argTypes, false);
132                     else
133                         callFeature = clazz.getConstructor(argTypes, false);
134                     if (callFeature != null) {
135                         declaringClasses.add(getRealClassDefinition(clazz));
136                     }
137                     q.addAll(clazz.getInterfaces());
138                     clazz = clazz.getSuperClass();
139                     if (clazz!=null) {
140                         q.add(clazz);
141                     }
142                 }
143             }
144         }
145     }
146     
147     private ClassDefinition getRealClassDefinition(ClassDefinition cls) {
148         return (ClassDefinition) TypeClassImpl.getRawType(cls);
149     }
150     
151     private Collection getUsers(MetadataElement where) {
152         usages = new ArrayList();
153         List l = new ArrayList(1);
154         l.add(where);
155         getUsers(l);
156         return usages;
157     }
158     
159     public Collection getUsers(Resource res[]) {
160         return new LazyCollection(res);
161     }
162     
163     private void getUsers(Collection elements) {
164         if (elements == null || elements.isEmpty())
165             return;
166         
167         for (Iterator iter = elements.iterator(); iter.hasNext();) {
168             MetadataElement el = (MetadataElement) iter.next();
169             if ((el instanceof Resource) || navigator.containsIdentifierIn(el)) {
170                 if (isMatch(what, el)) {
171                     usages.add(el);
172                 }
173                 getUsers(el.getChildren());
174             }
175         }
176     }
177     
178     private boolean isMatch(Element what, Element r) {
179         //I'm not usage of myself
180
if (what.equals(r))
181             return false;
182
183         Element ref = r;
184         if (findUsages) {
185             if (ref instanceof ElementReference) {
186                 ref = ((ElementReference) r).getElement();
187             } else {
188                 if (!overriders) {
189                     return false;
190                 }
191             }
192         }
193
194         if (!(what instanceof Method)) {
195             if (ref instanceof ParameterizedType) {
196                 ref = getRealClassDefinition((ParameterizedType) ref);
197             }
198             return what.equals(ref);
199         }
200
201 // if (!overriders) {
202
// if (ref instanceof Method)
203
// return false;
204
// }
205

206         if (!(ref instanceof Method)) {
207             return false;
208         }
209         
210         if (!overriders && what.equals(ref)) {
211             return true;
212         }
213         
214         Method m = (Method) ref;
215         if (m.signatureEquals((Method) what)) {
216             ClassDefinition collectedClass, declaringClass = getRealClassDefinition(m.getDeclaringClass());
217             for (Iterator i = declaringClasses.iterator(); i.hasNext();) {
218                 collectedClass = (ClassDefinition) i.next();
219                 if (declaringClass.isSubTypeOf(collectedClass)) {
220                     return true;
221                 }
222             }
223         }
224         return false;
225     }
226
227     private void lock() {
228         JavaMetamodel.getDefaultRepository().beginTrans(false);
229     }
230
231     private void unlock() {
232         JavaMetamodel.getDefaultRepository().endTrans(false);
233     }
234     
235     private class LazyCollection extends AbstractCollection {
236         MOFID res[];
237         
238         public LazyCollection(Resource res[]) {
239             this.res = new MOFID[res.length];
240             for (int i = 0; i < res.length; i++) {
241                 this.res[i] = ((MetadataElement) res[i])._getMofId();
242             }
243         }
244         
245         public Iterator iterator() {
246             return new LazyIterator(res);
247         }
248
249         public int size() {
250             lock();
251             try {
252                 int size = 0;
253                 for (Iterator i = iterator(); i.hasNext(); i.next(), size++ );
254                 return size;
255             } finally {
256                 unlock();
257             }
258         }
259
260         public boolean isEmpty() {
261             lock();
262             try {
263                 return !iterator().hasNext();
264             } finally {
265                 unlock();
266             }
267         }
268     }
269     
270     private class LazyIterator implements Iterator, Cancellable {
271         
272         MOFID res[];
273         Collection currentUsages = Collections.EMPTY_LIST;
274         Iterator inner;
275         int currentIndex;
276         Object JavaDoc next;
277         boolean hasNext;
278         float step;
279         int last;
280         ProgressSupport progressSupport;
281         private boolean cancelRequest;
282         
283         LazyIterator(MOFID[] res) {
284             this.res = res;
285             inner = currentUsages.iterator();
286             currentIndex = -1;
287             hasNext = true;
288             
289             step = 1;
290             if (res.length > MAX_COUNT) {
291                 step = (float) MAX_COUNT / res.length;
292             }
293             last = 0;
294         
295             progressSupport = JavaMetamodel.getManager().getProgressSupport();
296         }
297                 
298         public void remove() {
299             throw new UnsupportedOperationException JavaDoc();
300         }
301         
302         public Object JavaDoc next() {
303             lock();
304             try {
305                 if (next==null) {
306                     findNext();
307                 }
308                 Object JavaDoc result = next;
309                 next = null;
310                 return result;
311             } finally {
312                 unlock();
313             }
314         }
315         
316         private void findNext() {
317             if (!hasNext) {
318                 throw new NoSuchElementException();
319             }
320             while (next==null && hasNext == true) {
321                 if (!inner.hasNext()) {
322                     if (cancelRequest)
323                         return;
324                     currentIndex++;
325                     if (currentIndex == 0) {
326                         progressSupport.fireProgressListenerStart(0, Math.min(res.length,MAX_COUNT));
327                     }
328                     if (currentIndex < res.length) {
329                         MOFID mofId = res[currentIndex];
330                         if (mofId != null) {
331                             ResourceImpl resource = (ResourceImpl) ((NBMDRepositoryImpl) JMManager.getDefaultRepository()).getByMofId(mofId);
332                             try {
333                                 if (resource != null && !resource.getName().endsWith("class")) { // NOI18N
334
navigator = new ElementNavigator(resource, what);
335                                     currentUsages = getUsers(resource);
336                                     inner = currentUsages.iterator();
337                                     if (!inner.hasNext()) {
338                                         res[currentIndex] = null;
339                                     }
340                                 } else {
341                                     res[currentIndex] = null;
342                                 }
343                             } catch (IllegalArgumentException JavaDoc e) {
344                                 JMManager.getLog().notify(ErrorManager.INFORMATIONAL, new Exception JavaDoc("Resource " + resource == null ? null : resource.getName() + " is not parsable.", e)); // NOI18N
345
}
346                         }
347
348                         if (currentIndex*step >= last) {
349                             progressSupport.fireProgressListenerStep();
350                             last++;
351                         }
352
353                     } else {
354                         hasNext = false;
355                         progressSupport.fireProgressListenerStop();
356                     }
357                 }
358                 if (inner.hasNext()) {
359                     next = inner.next();
360                 }
361             }
362         }
363         
364         public boolean hasNext() {
365             lock();
366             try {
367                 findNext();
368                 if (cancelRequest)
369                     return false;
370                 return hasNext;
371             } finally {
372                 unlock();
373             }
374         }
375         
376         public boolean cancel() {
377             cancelRequest = true;
378             return true;
379         }
380     }
381 }
382
Popular Tags