KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > api > java > source > ClassIndex


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.netbeans.api.java.source;
21
22 import java.io.IOException JavaDoc;
23 import java.net.URL JavaDoc;
24 import java.util.Collections JavaDoc;
25 import java.util.EnumSet JavaDoc;
26 import java.util.HashSet JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Set JavaDoc;
29 import java.util.logging.Logger JavaDoc;
30 import javax.lang.model.element.ElementKind;
31 import javax.lang.model.element.TypeElement;
32 import org.netbeans.api.java.classpath.ClassPath;
33 import org.netbeans.modules.java.source.classpath.GlobalSourcePath;
34 import org.netbeans.modules.java.source.usages.ClassIndexFactory;
35 import org.netbeans.modules.java.source.usages.ClassIndexImpl;
36 import org.netbeans.modules.java.source.usages.ClassIndexManager;
37 import org.netbeans.modules.java.source.usages.Index;
38 import org.netbeans.modules.java.source.usages.ResultConvertor;
39 import org.openide.filesystems.FileObject;
40 import org.openide.util.Exceptions;
41
42 /**
43  * The ClassIndex provides access to information stored in the
44  * persistent index. It can be used to obtain list of packages
45  * or declared types. It can be also used to obtain a list of
46  * source files referencing given type (usages of given type).
47  *
48  * @author Petr Hrebejk, Tomas Zezula
49  */

50 public final class ClassIndex {
51     
52     private static final Logger JavaDoc LOGGER = Logger.getLogger(ClassIndex.class.getName());
53     
54     private final ClassPath bootPath;
55     private final ClassPath classPath;
56     private final ClassPath sourcePath;
57     
58     private Set JavaDoc<ClassIndexImpl> sourceIndeces;
59     private Set JavaDoc<ClassIndexImpl> depsIndeces;
60     
61     
62     
63     /**
64      * Encodes a type of the name kind used by
65      * {@link ClassIndex#getDeclaredTypes} method.
66      *
67      */

68     public enum NameKind {
69         /**
70          * The name parameter of the {@link ClassIndex#getDeclaredTypes}
71          * is an exact simple name of the package or declared type.
72          */

73         SIMPLE_NAME,
74         
75         /**
76          * The name parameter of the {@link ClassIndex#getDeclaredTypes}
77          * is an case sensitive prefix of the package or declared type name.
78          */

79         PREFIX,
80         
81         /**
82          * The name parameter of the {@link ClassIndex#getDeclaredTypes} is
83          * an case insensitive prefix of the declared type name.
84          */

85         CASE_INSENSITIVE_PREFIX,
86         
87         /**
88          * The name parameter of the {@link ClassIndex#getDeclaredTypes} is
89          * an camel case of the declared type name.
90          */

91         CAMEL_CASE,
92         
93         
94         /**
95          * The name parameter of the {@link ClassIndex#getDeclaredTypes} is
96          * an regular expression of the declared type name.
97          */

98         REGEXP,
99         
100         /**
101          * The name parameter of the {@link ClassIndex#getDeclaredTypes} is
102          * an case insensitive regular expression of the declared type name.
103          */

104         CASE_INSENSITIVE_REGEXP
105     };
106     
107     
108     /**
109      * Encodes a reference type,
110      * used by {@link ClassIndex#getElements} and {@link ClassIndex#getResources}
111      * to restrict the search.
112      */

113     public enum SearchKind {
114         
115         /**
116          * The returned class has to extend or implement given element
117          */

118         IMPLEMENTORS,
119         
120         /**
121          * The returned class has to call method on given element
122          */

123         METHOD_REFERENCES,
124         
125         /**
126          * The returned class has to access a field on given element
127          */

128         FIELD_REFERENCES,
129         
130         /**
131          * The returned class contains references to the element type
132          */

133         TYPE_REFERENCES,
134     };
135     
136     /**
137      * Scope used by {@link ClassIndex} to search in
138      */

139     public enum SearchScope {
140         /**
141          * Search is done in source path
142          */

143         SOURCE,
144         /**
145          * Search is done in compile and boot path
146          */

147         DEPENDENCIES
148     };
149     
150     static {
151     ClassIndexImpl.FACTORY = new ClassIndexFactoryImpl();
152     }
153     
154     ClassIndex(final ClassPath bootPath, final ClassPath classPath, final ClassPath sourcePath) {
155         assert bootPath != null;
156         assert classPath != null;
157         assert sourcePath != null;
158         this.bootPath = bootPath;
159         this.classPath = classPath;
160         this.sourcePath = sourcePath;
161     }
162     
163     
164     /**
165      * Returns a set of {@link ElementHandle}s containing reference(s) to given element.
166      * @param element for which usages should be found
167      * @param searchKind type of reference, {@see SearchKind}
168      * @param scope to search in {@see SearchScope}
169      * @return set of {@link ElementHandle}s containing the reference(s)
170      *
171      */

172     public Set JavaDoc<ElementHandle<TypeElement>> getElements (final ElementHandle<TypeElement> element, final Set JavaDoc<SearchKind> searchKind, final Set JavaDoc<SearchScope> scope) {
173         assert element != null;
174         assert element.getSignature()[0] != null;
175         assert searchKind != null;
176         final Set JavaDoc<ElementHandle<TypeElement>> result = new HashSet JavaDoc<ElementHandle<TypeElement>> ();
177         final Iterable JavaDoc<? extends ClassIndexImpl> queries = this.getQueries (scope);
178         final Set JavaDoc<ClassIndexImpl.UsageType> ut = encodeSearchKind(element.getKind(),searchKind);
179         final String JavaDoc binaryName = element.getSignature()[0];
180         final ResultConvertor<ElementHandle<TypeElement>> thConvertor = ResultConvertor.elementHandleConvertor();
181         if (!ut.isEmpty()) {
182             for (ClassIndexImpl query : queries) {
183                 query.search(binaryName, ut, thConvertor, result);
184             }
185         }
186         return Collections.unmodifiableSet(result);
187     }
188     
189     /**
190      * Returns a set of source files containing reference(s) to given element.
191      * @param element for which usages should be found
192      * @param searchKind type of reference, {@see SearchKind}
193      * @param scope to search in {@see SearchScope}
194      * @return set of {@link FileObject}s containing the reference(s)
195      *
196      */

197     public Set JavaDoc<FileObject> getResources (final ElementHandle<TypeElement> element, final Set JavaDoc<SearchKind> searchKind, final Set JavaDoc<SearchScope> scope) {
198         assert element != null;
199         assert element.getSignature()[0] != null;
200         assert searchKind != null;
201         final Set JavaDoc<FileObject> result = new HashSet JavaDoc<FileObject> ();
202         final Iterable JavaDoc<? extends ClassIndexImpl> queries = this.getQueries (scope);
203         final Set JavaDoc<ClassIndexImpl.UsageType> ut = encodeSearchKind(element.getKind(),searchKind);
204         final String JavaDoc binaryName = element.getSignature()[0];
205         if (!ut.isEmpty()) {
206             for (ClassIndexImpl query : queries) {
207                 final ResultConvertor<FileObject> foConvertor = ResultConvertor.fileObjectConvertor (query.getSourceRoots());
208                 query.search (binaryName, ut, foConvertor, result);
209             }
210         }
211         return Collections.unmodifiableSet(result);
212     }
213     
214     
215     /**
216      * Returns {@link ElementHandle}s for all declared types in given classpath corresponding to the name.
217      * @param case sensitive prefix, case insensitive prefix, exact simple name,
218      * camel case or regular expression depending on the kind parameter.
219      * @param kind of the name {@see NameKind}
220      * @param scope to search in {@see SearchScope}
221      * @return set of all matched declared types
222      */

223     public Set JavaDoc<ElementHandle<TypeElement>> getDeclaredTypes (final String JavaDoc name, final NameKind kind, final Set JavaDoc<SearchScope> scope) {
224         assert name != null;
225         assert kind != null;
226         final Set JavaDoc<ElementHandle<TypeElement>> result = new HashSet JavaDoc<ElementHandle<TypeElement>>();
227         final Iterable JavaDoc<? extends ClassIndexImpl> queries = this.getQueries (scope);
228         final ResultConvertor<ElementHandle<TypeElement>> thConvertor = ResultConvertor.elementHandleConvertor();
229         for (ClassIndexImpl query : queries) {
230             query.getDeclaredTypes (name, kind, thConvertor, result);
231         }
232         LOGGER.fine(String.format("ClassIndex.getDeclaredTypes returned %d elements\n", result.size()));
233         return Collections.unmodifiableSet(result);
234     }
235     
236     /**
237      * Returns names af all packages in given classpath starting with prefix.
238      * @param prefix of the package name
239      * @param directOnly if true treats the packages as folders and returns only
240      * the nearest component of the package.
241      * @param scope to search in {@see SearchScope}
242      * @return set of all matched package names
243      */

244     public Set JavaDoc<String JavaDoc> getPackageNames (final String JavaDoc prefix, boolean directOnly, final Set JavaDoc<SearchScope> scope) {
245         assert prefix != null;
246         final Set JavaDoc<String JavaDoc> result = new HashSet JavaDoc<String JavaDoc> ();
247         final Iterable JavaDoc<? extends ClassIndexImpl> queries = this.getQueries (scope);
248         for (ClassIndexImpl query : queries) {
249             query.getPackageNames (prefix, directOnly, result);
250         }
251         return Collections.unmodifiableSet(result);
252     }
253     
254     // Private innerclasses ----------------------------------------------------
255

256     private static class ClassIndexFactoryImpl implements ClassIndexFactory {
257         
258     public ClassIndex create(final ClassPath bootPath, final ClassPath classPath, final ClassPath sourcePath) {
259         return new ClassIndex(bootPath, classPath, sourcePath);
260         }
261     
262     }
263     
264     //Private methods
265

266     
267     private synchronized Iterable JavaDoc<? extends ClassIndexImpl> getQueries (final Set JavaDoc<SearchScope> scope) {
268         Set JavaDoc<ClassIndexImpl> result = new HashSet JavaDoc<ClassIndexImpl> ();
269         if (scope.contains(SearchScope.SOURCE)) {
270             if (this.sourceIndeces == null) {
271                 Set JavaDoc<ClassIndexImpl> indeces = new HashSet JavaDoc<ClassIndexImpl>();
272                 createQueriesForRoots (this.sourcePath, true, indeces);
273                 this.sourceIndeces = indeces;
274             }
275             result.addAll(this.sourceIndeces);
276         }
277         if (scope.contains(SearchScope.DEPENDENCIES)) {
278             if (this.depsIndeces == null) {
279                 Set JavaDoc<ClassIndexImpl> indeces = new HashSet JavaDoc<ClassIndexImpl>();
280                 createQueriesForRoots (this.bootPath, false, indeces);
281                 createQueriesForRoots (this.classPath, false, indeces);
282                 this.depsIndeces = indeces;
283             }
284             result.addAll(this.depsIndeces);
285         }
286         LOGGER.fine(String.format("ClassIndex.queries[Scope=%s, sourcePath=%s, bootPath=%s, classPath=%s] => %s\n",scope,sourcePath,bootPath,classPath,result));
287         return result;
288     }
289     
290     
291     private void createQueriesForRoots (final ClassPath cp, final boolean sources, final Set JavaDoc<? super ClassIndexImpl> queries) {
292         final GlobalSourcePath gsp = GlobalSourcePath.getDefault();
293         List JavaDoc<ClassPath.Entry> entries = cp.entries();
294     for (ClassPath.Entry entry : entries) {
295         try {
296                 boolean indexNow = false;
297                 URL JavaDoc[] srcRoots;
298                 if (!sources) {
299                     URL JavaDoc srcRoot = Index.getSourceRootForClassFolder (entry.getURL());
300                     if (srcRoot != null) {
301                         srcRoots = new URL JavaDoc[] {srcRoot};
302                     }
303                     else {
304                         srcRoots = gsp.getSourceRootForBinaryRoot (entry.getURL(), cp, true);
305                         if (srcRoots == null) {
306                             indexNow = true;
307                             srcRoots = new URL JavaDoc[] {entry.getURL()};
308                         }
309                     }
310                     //End to be removed
311
}
312                 else {
313                     srcRoots = new URL JavaDoc[] {entry.getURL()};
314                 }
315                 for (URL JavaDoc srcRoot : srcRoots) {
316                     ClassIndexImpl ci = ClassIndexManager.getDefault().getUsagesQuery(srcRoot);
317                     if (ci != null) {
318                         queries.add (ci);
319                     }
320                 }
321         } catch (IOException JavaDoc ioe) {
322         Exceptions.printStackTrace(ioe);
323         }
324     }
325     }
326     
327     
328     private static Set JavaDoc<ClassIndexImpl.UsageType> encodeSearchKind (final ElementKind elementKind, final Set JavaDoc<ClassIndex.SearchKind> kind) {
329         assert kind != null;
330         final Set JavaDoc<ClassIndexImpl.UsageType> result = EnumSet.noneOf(ClassIndexImpl.UsageType.class);
331         for (ClassIndex.SearchKind sk : kind) {
332             switch (sk) {
333                 case METHOD_REFERENCES:
334                     result.add(ClassIndexImpl.UsageType.METHOD_REFERENCE);
335                     break;
336                 case FIELD_REFERENCES:
337                     result.add(ClassIndexImpl.UsageType.FIELD_REFERENCE);
338                     break;
339                 case TYPE_REFERENCES:
340                     result.add(ClassIndexImpl.UsageType.TYPE_REFERENCE);
341                     break;
342                 case IMPLEMENTORS:
343                     switch( elementKind) {
344                         case INTERFACE:
345                         case ANNOTATION_TYPE:
346                             result.add(ClassIndexImpl.UsageType.SUPER_INTERFACE);
347                             break;
348                         case CLASS:
349                             result.add(ClassIndexImpl.UsageType.SUPER_CLASS);
350                             break;
351                         case ENUM: //enum is final
352
break;
353                         case OTHER:
354                             result.add(ClassIndexImpl.UsageType.SUPER_INTERFACE);
355                             result.add(ClassIndexImpl.UsageType.SUPER_CLASS);
356                             break;
357                         default:
358                             throw new IllegalArgumentException JavaDoc ();
359                     }
360                     break;
361                 default:
362                     throw new IllegalArgumentException JavaDoc ();
363             }
364         }
365         return result;
366     }
367     
368 }
369
Popular Tags