1 19 20 package org.netbeans.api.java.source; 21 22 import java.io.IOException ; 23 import java.net.URL ; 24 import java.util.Collections ; 25 import java.util.EnumSet ; 26 import java.util.HashSet ; 27 import java.util.List ; 28 import java.util.Set ; 29 import java.util.logging.Logger ; 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 50 public final class ClassIndex { 51 52 private static final Logger 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 <ClassIndexImpl> sourceIndeces; 59 private Set <ClassIndexImpl> depsIndeces; 60 61 62 63 68 public enum NameKind { 69 73 SIMPLE_NAME, 74 75 79 PREFIX, 80 81 85 CASE_INSENSITIVE_PREFIX, 86 87 91 CAMEL_CASE, 92 93 94 98 REGEXP, 99 100 104 CASE_INSENSITIVE_REGEXP 105 }; 106 107 108 113 public enum SearchKind { 114 115 118 IMPLEMENTORS, 119 120 123 METHOD_REFERENCES, 124 125 128 FIELD_REFERENCES, 129 130 133 TYPE_REFERENCES, 134 }; 135 136 139 public enum SearchScope { 140 143 SOURCE, 144 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 172 public Set <ElementHandle<TypeElement>> getElements (final ElementHandle<TypeElement> element, final Set <SearchKind> searchKind, final Set <SearchScope> scope) { 173 assert element != null; 174 assert element.getSignature()[0] != null; 175 assert searchKind != null; 176 final Set <ElementHandle<TypeElement>> result = new HashSet <ElementHandle<TypeElement>> (); 177 final Iterable <? extends ClassIndexImpl> queries = this.getQueries (scope); 178 final Set <ClassIndexImpl.UsageType> ut = encodeSearchKind(element.getKind(),searchKind); 179 final String 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 197 public Set <FileObject> getResources (final ElementHandle<TypeElement> element, final Set <SearchKind> searchKind, final Set <SearchScope> scope) { 198 assert element != null; 199 assert element.getSignature()[0] != null; 200 assert searchKind != null; 201 final Set <FileObject> result = new HashSet <FileObject> (); 202 final Iterable <? extends ClassIndexImpl> queries = this.getQueries (scope); 203 final Set <ClassIndexImpl.UsageType> ut = encodeSearchKind(element.getKind(),searchKind); 204 final String 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 223 public Set <ElementHandle<TypeElement>> getDeclaredTypes (final String name, final NameKind kind, final Set <SearchScope> scope) { 224 assert name != null; 225 assert kind != null; 226 final Set <ElementHandle<TypeElement>> result = new HashSet <ElementHandle<TypeElement>>(); 227 final Iterable <? 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 244 public Set <String > getPackageNames (final String prefix, boolean directOnly, final Set <SearchScope> scope) { 245 assert prefix != null; 246 final Set <String > result = new HashSet <String > (); 247 final Iterable <? 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 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 266 267 private synchronized Iterable <? extends ClassIndexImpl> getQueries (final Set <SearchScope> scope) { 268 Set <ClassIndexImpl> result = new HashSet <ClassIndexImpl> (); 269 if (scope.contains(SearchScope.SOURCE)) { 270 if (this.sourceIndeces == null) { 271 Set <ClassIndexImpl> indeces = new HashSet <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 <ClassIndexImpl> indeces = new HashSet <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 <? super ClassIndexImpl> queries) { 292 final GlobalSourcePath gsp = GlobalSourcePath.getDefault(); 293 List <ClassPath.Entry> entries = cp.entries(); 294 for (ClassPath.Entry entry : entries) { 295 try { 296 boolean indexNow = false; 297 URL [] srcRoots; 298 if (!sources) { 299 URL srcRoot = Index.getSourceRootForClassFolder (entry.getURL()); 300 if (srcRoot != null) { 301 srcRoots = new URL [] {srcRoot}; 302 } 303 else { 304 srcRoots = gsp.getSourceRootForBinaryRoot (entry.getURL(), cp, true); 305 if (srcRoots == null) { 306 indexNow = true; 307 srcRoots = new URL [] {entry.getURL()}; 308 } 309 } 310 } 312 else { 313 srcRoots = new URL [] {entry.getURL()}; 314 } 315 for (URL srcRoot : srcRoots) { 316 ClassIndexImpl ci = ClassIndexManager.getDefault().getUsagesQuery(srcRoot); 317 if (ci != null) { 318 queries.add (ci); 319 } 320 } 321 } catch (IOException ioe) { 322 Exceptions.printStackTrace(ioe); 323 } 324 } 325 } 326 327 328 private static Set <ClassIndexImpl.UsageType> encodeSearchKind (final ElementKind elementKind, final Set <ClassIndex.SearchKind> kind) { 329 assert kind != null; 330 final Set <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: 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 (); 359 } 360 break; 361 default: 362 throw new IllegalArgumentException (); 363 } 364 } 365 return result; 366 } 367 368 } 369 | Popular Tags |