/*******************************************************************************
* 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;
}
}
}