001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.core.hierarchy;
011:
012: import java.util.ArrayList;
013: import java.util.HashMap;
014: import java.util.Iterator;
015: import java.util.Map;
016:
017: import org.eclipse.core.runtime.IProgressMonitor;
018: import org.eclipse.core.runtime.SubProgressMonitor;
019: import org.eclipse.jdt.core.IClassFile;
020: import org.eclipse.jdt.core.ICompilationUnit;
021: import org.eclipse.jdt.core.IJavaElement;
022: import org.eclipse.jdt.core.IJavaProject;
023: import org.eclipse.jdt.core.IPackageFragment;
024: import org.eclipse.jdt.core.IPackageFragmentRoot;
025: import org.eclipse.jdt.core.IType;
026: import org.eclipse.jdt.core.JavaModelException;
027: import org.eclipse.jdt.internal.core.JavaModelManager;
028: import org.eclipse.jdt.internal.core.JavaProject;
029: import org.eclipse.jdt.internal.core.Openable;
030: import org.eclipse.jdt.internal.core.SearchableEnvironment;
031:
032: public class RegionBasedHierarchyBuilder extends HierarchyBuilder {
033:
034: public RegionBasedHierarchyBuilder(TypeHierarchy hierarchy)
035: throws JavaModelException {
036:
037: super (hierarchy);
038: }
039:
040: public void build(boolean computeSubtypes) {
041:
042: JavaModelManager manager = JavaModelManager
043: .getJavaModelManager();
044: try {
045: // optimize access to zip files while building hierarchy
046: manager.cacheZipFiles();
047:
048: if (this .hierarchy.focusType == null || computeSubtypes) {
049: IProgressMonitor typeInRegionMonitor = this .hierarchy.progressMonitor == null ? null
050: : new SubProgressMonitor(
051: this .hierarchy.progressMonitor, 30);
052: HashMap allOpenablesInRegion = determineOpenablesInRegion(typeInRegionMonitor);
053: this .hierarchy.initialize(allOpenablesInRegion.size());
054: IProgressMonitor buildMonitor = this .hierarchy.progressMonitor == null ? null
055: : new SubProgressMonitor(
056: this .hierarchy.progressMonitor, 70);
057: createTypeHierarchyBasedOnRegion(allOpenablesInRegion,
058: buildMonitor);
059: ((RegionBasedTypeHierarchy) this .hierarchy)
060: .pruneDeadBranches();
061: } else {
062: this .hierarchy.initialize(1);
063: this .buildSupertypes();
064: }
065: } finally {
066: manager.flushZipFiles();
067: }
068: }
069:
070: /**
071: * Configure this type hierarchy that is based on a region.
072: */
073: private void createTypeHierarchyBasedOnRegion(
074: HashMap allOpenablesInRegion, IProgressMonitor monitor) {
075:
076: try {
077: int size = allOpenablesInRegion.size();
078: if (monitor != null)
079: monitor
080: .beginTask("", size * 2/* 1 for build binding, 1 for connect hierarchy*/); //$NON-NLS-1$
081: this .infoToHandle = new HashMap(size);
082: Iterator javaProjects = allOpenablesInRegion.entrySet()
083: .iterator();
084: while (javaProjects.hasNext()) {
085: Map.Entry entry = (Map.Entry) javaProjects.next();
086: JavaProject project = (JavaProject) entry.getKey();
087: ArrayList allOpenables = (ArrayList) entry.getValue();
088: Openable[] openables = new Openable[allOpenables.size()];
089: allOpenables.toArray(openables);
090:
091: try {
092: // resolve
093: SearchableEnvironment searchableEnvironment = project
094: .newSearchableNameEnvironment(this .hierarchy.workingCopies);
095: this .nameLookup = searchableEnvironment.nameLookup;
096: this .hierarchyResolver.resolve(openables, null,
097: monitor);
098: } catch (JavaModelException e) {
099: // project doesn't exit: ignore
100: }
101: }
102: } finally {
103: if (monitor != null)
104: monitor.done();
105: }
106: }
107:
108: /**
109: * Returns all of the openables defined in the region of this type hierarchy.
110: * Returns a map from IJavaProject to ArrayList of Openable
111: */
112: private HashMap determineOpenablesInRegion(IProgressMonitor monitor) {
113:
114: try {
115: HashMap allOpenables = new HashMap();
116: IJavaElement[] roots = ((RegionBasedTypeHierarchy) this .hierarchy).region
117: .getElements();
118: int length = roots.length;
119: if (monitor != null)
120: monitor.beginTask("", length); //$NON-NLS-1$
121: for (int i = 0; i < length; i++) {
122: IJavaElement root = roots[i];
123: IJavaProject javaProject = root.getJavaProject();
124: ArrayList openables = (ArrayList) allOpenables
125: .get(javaProject);
126: if (openables == null) {
127: openables = new ArrayList();
128: allOpenables.put(javaProject, openables);
129: }
130: switch (root.getElementType()) {
131: case IJavaElement.JAVA_PROJECT:
132: injectAllOpenablesForJavaProject(
133: (IJavaProject) root, openables);
134: break;
135: case IJavaElement.PACKAGE_FRAGMENT_ROOT:
136: injectAllOpenablesForPackageFragmentRoot(
137: (IPackageFragmentRoot) root, openables);
138: break;
139: case IJavaElement.PACKAGE_FRAGMENT:
140: injectAllOpenablesForPackageFragment(
141: (IPackageFragment) root, openables);
142: break;
143: case IJavaElement.CLASS_FILE:
144: case IJavaElement.COMPILATION_UNIT:
145: openables.add(root);
146: break;
147: case IJavaElement.TYPE:
148: IType type = (IType) root;
149: if (type.isBinary()) {
150: openables.add(type.getClassFile());
151: } else {
152: openables.add(type.getCompilationUnit());
153: }
154: break;
155: default:
156: break;
157: }
158: worked(monitor, 1);
159: }
160: return allOpenables;
161: } finally {
162: if (monitor != null)
163: monitor.done();
164: }
165: }
166:
167: /**
168: * Adds all of the openables defined within this java project to the
169: * list.
170: */
171: private void injectAllOpenablesForJavaProject(IJavaProject project,
172: ArrayList openables) {
173: try {
174: IPackageFragmentRoot[] devPathRoots = ((JavaProject) project)
175: .getPackageFragmentRoots();
176: if (devPathRoots == null) {
177: return;
178: }
179: for (int j = 0; j < devPathRoots.length; j++) {
180: IPackageFragmentRoot root = devPathRoots[j];
181: injectAllOpenablesForPackageFragmentRoot(root,
182: openables);
183: }
184: } catch (JavaModelException e) {
185: // ignore
186: }
187: }
188:
189: /**
190: * Adds all of the openables defined within this package fragment to the
191: * list.
192: */
193: private void injectAllOpenablesForPackageFragment(
194: IPackageFragment packFrag, ArrayList openables) {
195:
196: try {
197: IPackageFragmentRoot root = (IPackageFragmentRoot) packFrag
198: .getParent();
199: int kind = root.getKind();
200: if (kind != 0) {
201: boolean isSourcePackageFragment = (kind == IPackageFragmentRoot.K_SOURCE);
202: if (isSourcePackageFragment) {
203: ICompilationUnit[] cus = packFrag
204: .getCompilationUnits();
205: for (int i = 0, length = cus.length; i < length; i++) {
206: openables.add(cus[i]);
207: }
208: } else {
209: IClassFile[] classFiles = packFrag.getClassFiles();
210: for (int i = 0, length = classFiles.length; i < length; i++) {
211: openables.add(classFiles[i]);
212: }
213: }
214: }
215: } catch (JavaModelException e) {
216: // ignore
217: }
218: }
219:
220: /**
221: * Adds all of the openables defined within this package fragment root to the
222: * list.
223: */
224: private void injectAllOpenablesForPackageFragmentRoot(
225: IPackageFragmentRoot root, ArrayList openables) {
226: try {
227: IJavaElement[] packFrags = root.getChildren();
228: for (int k = 0; k < packFrags.length; k++) {
229: IPackageFragment packFrag = (IPackageFragment) packFrags[k];
230: injectAllOpenablesForPackageFragment(packFrag,
231: openables);
232: }
233: } catch (JavaModelException e) {
234: return;
235: }
236: }
237:
238: }
|