| /******************************************************************************* |
| * Copyright (c) 2000, 2009 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.core.hierarchy; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.SubProgressMonitor; |
| import org.eclipse.jdt.core.IClassFile; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IPackageFragment; |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.internal.core.JavaModelManager; |
| import org.eclipse.jdt.internal.core.JavaProject; |
| import org.eclipse.jdt.internal.core.Openable; |
| import org.eclipse.jdt.internal.core.SearchableEnvironment; |
| |
| public class RegionBasedHierarchyBuilder extends HierarchyBuilder { |
| |
| public RegionBasedHierarchyBuilder(TypeHierarchy hierarchy) |
| throws JavaModelException { |
| |
| super(hierarchy); |
| } |
| |
| public void build(boolean computeSubtypes) { |
| |
| JavaModelManager manager = JavaModelManager.getJavaModelManager(); |
| try { |
| // optimize access to zip files while building hierarchy |
| manager.cacheZipFiles(this); |
| |
| if (this.hierarchy.focusType == null || computeSubtypes) { |
| IProgressMonitor typeInRegionMonitor = |
| this.hierarchy.progressMonitor == null ? |
| null : |
| new SubProgressMonitor(this.hierarchy.progressMonitor, 30); |
| HashMap allOpenablesInRegion = determineOpenablesInRegion(typeInRegionMonitor); |
| this.hierarchy.initialize(allOpenablesInRegion.size()); |
| IProgressMonitor buildMonitor = |
| this.hierarchy.progressMonitor == null ? |
| null : |
| new SubProgressMonitor(this.hierarchy.progressMonitor, 70); |
| createTypeHierarchyBasedOnRegion(allOpenablesInRegion, buildMonitor); |
| ((RegionBasedTypeHierarchy)this.hierarchy).pruneDeadBranches(); |
| } else { |
| this.hierarchy.initialize(1); |
| buildSupertypes(); |
| } |
| } finally { |
| manager.flushZipFiles(this); |
| } |
| } |
| /** |
| * Configure this type hierarchy that is based on a region. |
| */ |
| private void createTypeHierarchyBasedOnRegion(HashMap allOpenablesInRegion, IProgressMonitor monitor) { |
| |
| try { |
| int size = allOpenablesInRegion.size(); |
| if (monitor != null) monitor.beginTask("", size * 2/* 1 for build binding, 1 for connect hierarchy*/); //$NON-NLS-1$ |
| this.infoToHandle = new HashMap(size); |
| Iterator javaProjects = allOpenablesInRegion.entrySet().iterator(); |
| while (javaProjects.hasNext()) { |
| Map.Entry entry = (Map.Entry) javaProjects.next(); |
| JavaProject project = (JavaProject) entry.getKey(); |
| ArrayList allOpenables = (ArrayList) entry.getValue(); |
| Openable[] openables = new Openable[allOpenables.size()]; |
| allOpenables.toArray(openables); |
| |
| try { |
| // resolve |
| SearchableEnvironment searchableEnvironment = project.newSearchableNameEnvironment(this.hierarchy.workingCopies); |
| this.nameLookup = searchableEnvironment.nameLookup; |
| this.hierarchyResolver.resolve(openables, null, monitor); |
| } catch (JavaModelException e) { |
| // project doesn't exit: ignore |
| } |
| } |
| } finally { |
| if (monitor != null) monitor.done(); |
| } |
| } |
| |
| /** |
| * Returns all of the openables defined in the region of this type hierarchy. |
| * Returns a map from IJavaProject to ArrayList of Openable |
| */ |
| private HashMap determineOpenablesInRegion(IProgressMonitor monitor) { |
| |
| try { |
| HashMap allOpenables = new HashMap(); |
| IJavaElement[] roots = |
| ((RegionBasedTypeHierarchy) this.hierarchy).region.getElements(); |
| int length = roots.length; |
| if (monitor != null) monitor.beginTask("", length); //$NON-NLS-1$ |
| for (int i = 0; i <length; i++) { |
| IJavaElement root = roots[i]; |
| IJavaProject javaProject = root.getJavaProject(); |
| ArrayList openables = (ArrayList) allOpenables.get(javaProject); |
| if (openables == null) { |
| openables = new ArrayList(); |
| allOpenables.put(javaProject, openables); |
| } |
| switch (root.getElementType()) { |
| case IJavaElement.JAVA_PROJECT : |
| injectAllOpenablesForJavaProject((IJavaProject) root, openables); |
| break; |
| case IJavaElement.PACKAGE_FRAGMENT_ROOT : |
| injectAllOpenablesForPackageFragmentRoot((IPackageFragmentRoot) root, openables); |
| break; |
| case IJavaElement.PACKAGE_FRAGMENT : |
| injectAllOpenablesForPackageFragment((IPackageFragment) root, openables); |
| break; |
| case IJavaElement.CLASS_FILE : |
| case IJavaElement.COMPILATION_UNIT : |
| openables.add(root); |
| break; |
| case IJavaElement.TYPE : |
| IType type = (IType)root; |
| if (type.isBinary()) { |
| openables.add(type.getClassFile()); |
| } else { |
| openables.add(type.getCompilationUnit()); |
| } |
| break; |
| default : |
| break; |
| } |
| worked(monitor, 1); |
| } |
| return allOpenables; |
| } finally { |
| if (monitor != null) monitor.done(); |
| } |
| } |
| |
| /** |
| * Adds all of the openables defined within this java project to the |
| * list. |
| */ |
| private void injectAllOpenablesForJavaProject( |
| IJavaProject project, |
| ArrayList openables) { |
| try { |
| IPackageFragmentRoot[] devPathRoots = |
| ((JavaProject) project).getPackageFragmentRoots(); |
| if (devPathRoots == null) { |
| return; |
| } |
| for (int j = 0; j < devPathRoots.length; j++) { |
| IPackageFragmentRoot root = devPathRoots[j]; |
| injectAllOpenablesForPackageFragmentRoot(root, openables); |
| } |
| } catch (JavaModelException e) { |
| // ignore |
| } |
| } |
| |
| /** |
| * Adds all of the openables defined within this package fragment to the |
| * list. |
| */ |
| private void injectAllOpenablesForPackageFragment( |
| IPackageFragment packFrag, |
| ArrayList openables) { |
| |
| try { |
| IPackageFragmentRoot root = (IPackageFragmentRoot) packFrag.getParent(); |
| int kind = root.getKind(); |
| if (kind != 0) { |
| boolean isSourcePackageFragment = (kind == IPackageFragmentRoot.K_SOURCE); |
| if (isSourcePackageFragment) { |
| ICompilationUnit[] cus = packFrag.getCompilationUnits(); |
| for (int i = 0, length = cus.length; i < length; i++) { |
| openables.add(cus[i]); |
| } |
| } else { |
| IClassFile[] classFiles = packFrag.getClassFiles(); |
| for (int i = 0, length = classFiles.length; i < length; i++) { |
| openables.add(classFiles[i]); |
| } |
| } |
| } |
| } catch (JavaModelException e) { |
| // ignore |
| } |
| } |
| |
| /** |
| * Adds all of the openables defined within this package fragment root to the |
| * list. |
| */ |
| private void injectAllOpenablesForPackageFragmentRoot( |
| IPackageFragmentRoot root, |
| ArrayList openables) { |
| try { |
| IJavaElement[] packFrags = root.getChildren(); |
| for (int k = 0; k < packFrags.length; k++) { |
| IPackageFragment packFrag = (IPackageFragment) packFrags[k]; |
| injectAllOpenablesForPackageFragment(packFrag, openables); |
| } |
| } catch (JavaModelException e) { |
| return; |
| } |
| } |
| |
| } |