KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > search > HierarchyScope


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.core.search;
12
13 import java.io.File JavaDoc;
14 import java.util.HashMap JavaDoc;
15 import java.util.HashSet JavaDoc;
16 import java.util.Iterator JavaDoc;
17
18 import org.eclipse.core.resources.*;
19 import org.eclipse.core.runtime.IPath;
20 import org.eclipse.jdt.core.*;
21 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
22 import org.eclipse.jdt.internal.core.*;
23 import org.eclipse.jdt.internal.core.JarPackageFragmentRoot;
24 import org.eclipse.jdt.internal.core.JavaElement;
25 import org.eclipse.jdt.internal.core.JavaModel;
26 import org.eclipse.jdt.internal.core.hierarchy.TypeHierarchy;
27
28 /**
29  * Scope limited to the subtype and supertype hierarchy of a given type.
30  */

31 public class HierarchyScope extends AbstractSearchScope implements SuffixConstants {
32
33     public IType focusType;
34     private String JavaDoc focusPath;
35     private WorkingCopyOwner owner;
36     
37     private ITypeHierarchy hierarchy;
38     private IType[] types;
39     private HashSet JavaDoc resourcePaths;
40     private IPath[] enclosingProjectsAndJars;
41
42     protected IResource[] elements;
43     protected int elementCount;
44     
45     public boolean needsRefresh;
46
47     /* (non-Javadoc)
48      * Adds the given resource to this search scope.
49      */

50     public void add(IResource element) {
51         if (this.elementCount == this.elements.length) {
52             System.arraycopy(
53                 this.elements,
54                 0,
55                 this.elements = new IResource[this.elementCount * 2],
56                 0,
57                 this.elementCount);
58         }
59         elements[elementCount++] = element;
60     }
61     
62     /* (non-Javadoc)
63      * Creates a new hiearchy scope for the given type.
64      */

65     public HierarchyScope(IType type, WorkingCopyOwner owner) throws JavaModelException {
66         this.focusType = type;
67         this.owner = owner;
68         
69         this.enclosingProjectsAndJars = this.computeProjectsAndJars(type);
70
71         // resource path
72
IPackageFragmentRoot root = (IPackageFragmentRoot)type.getPackageFragment().getParent();
73         if (root.isArchive()) {
74             IPath jarPath = root.getPath();
75             Object JavaDoc target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), jarPath, true);
76             String JavaDoc zipFileName;
77             if (target instanceof IFile) {
78                 // internal jar
79
zipFileName = jarPath.toString();
80             } else if (target instanceof File JavaDoc) {
81                 // external jar
82
zipFileName = ((File JavaDoc)target).getPath();
83             } else {
84                 return; // unknown target
85
}
86             this.focusPath =
87                 zipFileName
88                     + JAR_FILE_ENTRY_SEPARATOR
89                     + type.getFullyQualifiedName().replace('.', '/')
90                     + SUFFIX_STRING_class;
91         } else {
92             this.focusPath = type.getPath().toString();
93         }
94         
95         this.needsRefresh = true;
96             
97         //disabled for now as this could be expensive
98
//JavaModelManager.getJavaModelManager().rememberScope(this);
99
}
100     private void buildResourceVector() {
101         HashMap JavaDoc resources = new HashMap JavaDoc();
102         HashMap JavaDoc paths = new HashMap JavaDoc();
103         this.types = this.hierarchy.getAllTypes();
104         IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
105         for (int i = 0; i < this.types.length; i++) {
106             IType type = this.types[i];
107             IResource resource = type.getResource();
108             if (resource != null && resources.get(resource) == null) {
109                 resources.put(resource, resource);
110                 add(resource);
111             }
112             IPackageFragmentRoot root =
113                 (IPackageFragmentRoot) type.getPackageFragment().getParent();
114             if (root instanceof JarPackageFragmentRoot) {
115                 // type in a jar
116
JarPackageFragmentRoot jar = (JarPackageFragmentRoot) root;
117                 IPath jarPath = jar.getPath();
118                 Object JavaDoc target = JavaModel.getTarget(workspaceRoot, jarPath, true);
119                 String JavaDoc zipFileName;
120                 if (target instanceof IFile) {
121                     // internal jar
122
zipFileName = jarPath.toString();
123                 } else if (target instanceof File JavaDoc) {
124                     // external jar
125
zipFileName = ((File JavaDoc)target).getPath();
126                 } else {
127                     continue; // unknown target
128
}
129                 String JavaDoc resourcePath =
130                     zipFileName
131                         + JAR_FILE_ENTRY_SEPARATOR
132                         + type.getFullyQualifiedName().replace('.', '/')
133                         + SUFFIX_STRING_class;
134                 
135                 this.resourcePaths.add(resourcePath);
136                 paths.put(jarPath, type);
137             } else {
138                 // type is a project
139
paths.put(type.getJavaProject().getProject().getFullPath(), type);
140             }
141         }
142         this.enclosingProjectsAndJars = new IPath[paths.size()];
143         int i = 0;
144         for (Iterator JavaDoc iter = paths.keySet().iterator(); iter.hasNext();) {
145             this.enclosingProjectsAndJars[i++] = (IPath) iter.next();
146         }
147     }
148     /*
149      * Computes the paths of projects and jars that the hierarchy on the given type could contain.
150      * This is a super set of the project and jar paths once the hierarchy is computed.
151      */

152     private IPath[] computeProjectsAndJars(IType type) throws JavaModelException {
153         HashSet JavaDoc set = new HashSet JavaDoc();
154         IPackageFragmentRoot root = (IPackageFragmentRoot)type.getPackageFragment().getParent();
155         if (root.isArchive()) {
156             // add the root
157
set.add(root.getPath());
158             // add all projects that reference this archive and their dependents
159
IPath rootPath = root.getPath();
160             IJavaModel model = JavaModelManager.getJavaModelManager().getJavaModel();
161             IJavaProject[] projects = model.getJavaProjects();
162             HashSet JavaDoc visited = new HashSet JavaDoc();
163             for (int i = 0; i < projects.length; i++) {
164                 JavaProject project = (JavaProject) projects[i];
165                 IClasspathEntry entry = project.getClasspathEntryFor(rootPath);
166                 if (entry != null) {
167                     // add the project and its binary pkg fragment roots
168
IPackageFragmentRoot[] roots = project.getAllPackageFragmentRoots();
169                     set.add(project.getPath());
170                     for (int k = 0; k < roots.length; k++) {
171                         IPackageFragmentRoot pkgFragmentRoot = roots[k];
172                         if (pkgFragmentRoot.getKind() == IPackageFragmentRoot.K_BINARY) {
173                             set.add(pkgFragmentRoot.getPath());
174                         }
175                     }
176                     // add the dependent projects
177
this.computeDependents(project, set, visited);
178                 }
179             }
180         } else {
181             // add all the project's pkg fragment roots
182
IJavaProject project = (IJavaProject)root.getParent();
183             IPackageFragmentRoot[] roots = project.getAllPackageFragmentRoots();
184             for (int i = 0; i < roots.length; i++) {
185                 IPackageFragmentRoot pkgFragmentRoot = roots[i];
186                 if (pkgFragmentRoot.getKind() == IPackageFragmentRoot.K_BINARY) {
187                     set.add(pkgFragmentRoot.getPath());
188                 } else {
189                     set.add(pkgFragmentRoot.getParent().getPath());
190                 }
191             }
192             // add the dependent projects
193
this.computeDependents(project, set, new HashSet JavaDoc());
194         }
195         IPath[] result = new IPath[set.size()];
196         set.toArray(result);
197         return result;
198     }
199     private void computeDependents(IJavaProject project, HashSet JavaDoc set, HashSet JavaDoc visited) {
200         if (visited.contains(project)) return;
201         visited.add(project);
202         IProject[] dependents = project.getProject().getReferencingProjects();
203         for (int i = 0; i < dependents.length; i++) {
204             try {
205                 IJavaProject dependent = JavaCore.create(dependents[i]);
206                 IPackageFragmentRoot[] roots = dependent.getPackageFragmentRoots();
207                 set.add(dependent.getPath());
208                 for (int j = 0; j < roots.length; j++) {
209                     IPackageFragmentRoot pkgFragmentRoot = roots[j];
210                     if (pkgFragmentRoot.isArchive()) {
211                         set.add(pkgFragmentRoot.getPath());
212                     }
213                 }
214                 this.computeDependents(dependent, set, visited);
215             } catch (JavaModelException e) {
216                 // project is not a java project
217
}
218         }
219     }
220     /* (non-Javadoc)
221      * @see IJavaSearchScope#encloses(String)
222      */

223     public boolean encloses(String JavaDoc resourcePath) {
224         if (this.hierarchy == null) {
225             if (resourcePath.equals(this.focusPath)) {
226                 return true;
227             } else {
228                 if (this.needsRefresh) {
229                     try {
230                         this.initialize();
231                     } catch (JavaModelException e) {
232                         return false;
233                     }
234                 } else {
235                     // the scope is used only to find enclosing projects and jars
236
// clients is responsible for filtering out elements not in the hierarchy (see SearchEngine)
237
return true;
238                 }
239             }
240         }
241         if (this.needsRefresh) {
242             try {
243                 this.refresh();
244             } catch(JavaModelException e) {
245                 return false;
246             }
247         }
248         int separatorIndex = resourcePath.indexOf(JAR_FILE_ENTRY_SEPARATOR);
249         if (separatorIndex != -1) {
250             return this.resourcePaths.contains(resourcePath);
251         } else {
252             for (int i = 0; i < this.elementCount; i++) {
253                 if (resourcePath.startsWith(this.elements[i].getFullPath().toString())) {
254                     return true;
255                 }
256             }
257         }
258         return false;
259     }
260     /* (non-Javadoc)
261      * @see IJavaSearchScope#encloses(IJavaElement)
262      */

263     public boolean encloses(IJavaElement element) {
264         if (this.hierarchy == null) {
265             if (this.focusType.equals(element.getAncestor(IJavaElement.TYPE))) {
266                 return true;
267             } else {
268                 if (this.needsRefresh) {
269                     try {
270                         this.initialize();
271                     } catch (JavaModelException e) {
272                         return false;
273                     }
274                 } else {
275                     // the scope is used only to find enclosing projects and jars
276
// clients is responsible for filtering out elements not in the hierarchy (see SearchEngine)
277
return true;
278                 }
279             }
280         }
281         if (this.needsRefresh) {
282             try {
283                 this.refresh();
284             } catch(JavaModelException e) {
285                 return false;
286             }
287         }
288         IType type = null;
289         if (element instanceof IType) {
290             type = (IType) element;
291         } else if (element instanceof IMember) {
292             type = ((IMember) element).getDeclaringType();
293         }
294         if (type != null) {
295             if (this.hierarchy.contains(type)) {
296                 return true;
297             } else {
298                 // be flexible: look at original element (see bug 14106 Declarations in Hierarchy does not find declarations in hierarchy)
299
IType original;
300                 if (!type.isBinary()
301                         && (original = (IType)type.getPrimaryElement()) != null) {
302                     return this.hierarchy.contains(original);
303                 }
304             }
305         }
306         return false;
307     }
308     /* (non-Javadoc)
309      * @see IJavaSearchScope#enclosingProjectsAndJars()
310      * @deprecated
311      */

312     public IPath[] enclosingProjectsAndJars() {
313         if (this.needsRefresh) {
314             try {
315                 this.refresh();
316             } catch(JavaModelException e) {
317                 return new IPath[0];
318             }
319         }
320         return this.enclosingProjectsAndJars;
321     }
322     protected void initialize() throws JavaModelException {
323         this.resourcePaths = new HashSet JavaDoc();
324         this.elements = new IResource[5];
325         this.elementCount = 0;
326         this.needsRefresh = false;
327         if (this.hierarchy == null) {
328             this.hierarchy = this.focusType.newTypeHierarchy(this.owner, null);
329         } else {
330             this.hierarchy.refresh(null);
331         }
332         this.buildResourceVector();
333     }
334     /*
335      * @see AbstractSearchScope#processDelta(IJavaElementDelta)
336      */

337     public void processDelta(IJavaElementDelta delta) {
338         if (this.needsRefresh) return;
339         this.needsRefresh = this.hierarchy == null ? false : ((TypeHierarchy)this.hierarchy).isAffected(delta);
340     }
341     protected void refresh() throws JavaModelException {
342         if (this.hierarchy != null) {
343             this.initialize();
344         }
345     }
346     public String JavaDoc toString() {
347         return "HierarchyScope on " + ((JavaElement)this.focusType).toStringWithAncestors(); //$NON-NLS-1$
348
}
349
350 }
351
Popular Tags