/*******************************************************************************
* Copyright (c) 2000, 2006 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.rubypeople.rdt.internal.core.hierarchy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.rubypeople.rdt.core.IOpenable;
import org.rubypeople.rdt.core.IRubyElement;
import org.rubypeople.rdt.core.IRubyProject;
import org.rubypeople.rdt.core.IRubyScript;
import org.rubypeople.rdt.core.ISourceFolder;
import org.rubypeople.rdt.core.ISourceFolderRoot;
import org.rubypeople.rdt.core.IType;
import org.rubypeople.rdt.core.RubyModelException;
import org.rubypeople.rdt.internal.core.RubyProject;
public class RegionBasedHierarchyBuilder extends HierarchyBuilder {
public RegionBasedHierarchyBuilder(TypeHierarchy hierarchy)
throws RubyModelException {
super(hierarchy);
}
public void build(boolean computeSubtypes) {
// RubyModelManager manager = RubyModelManager.getRubyModelManager();
try {
// optimize access to zip files while building hierarchy
// manager.cacheZipFiles();
if (this.hierarchy.focusType == null || computeSubtypes) {
IProgressMonitor typeInRegionMonitor =
this.hierarchy.progressMonitor == null ?
null :
new SubProgressMonitor(this.hierarchy.progressMonitor, 30);
HashMap<IRubyProject, ArrayList<IOpenable>> 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);
this.buildSupertypes();
}
} finally {
// manager.flushZipFiles();
}
}
/**
* Configure this type hierarchy that is based on a region.
*/
private void createTypeHierarchyBasedOnRegion(HashMap<IRubyProject, ArrayList<IOpenable>> allOpenablesInRegion, IProgressMonitor monitor) {
int size = allOpenablesInRegion.size();
if (size == 0) {
if (monitor != null) monitor.done();
return;
}
this.infoToHandle = new HashMap(size);
Iterator<IRubyProject> rubyProjects = allOpenablesInRegion.keySet().iterator();
while (rubyProjects.hasNext()) {
IRubyProject project = rubyProjects.next();
ArrayList<IOpenable> allOpenables = allOpenablesInRegion.get(project);
IOpenable[] openables = new IOpenable[allOpenables.size()];
allOpenables.toArray(openables);
try {
// resolve
if (monitor != null) monitor.beginTask("", size * 2/* 1 for build binding, 1 for connect hierarchy*/); //$NON-NLS-1$
// SearchableEnvironment searchableEnvironment = project.newSearchableNameEnvironment(this.hierarchy.workingCopies);
// this.nameLookup = searchableEnvironment.nameLookup;
this.hierarchyResolver.resolve(openables, null, monitor);
// } catch (RubyModelException 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 IRubyProject to ArrayList of Openable
*/
private HashMap<IRubyProject, ArrayList<IOpenable>> determineOpenablesInRegion(IProgressMonitor monitor) {
try {
HashMap<IRubyProject, ArrayList<IOpenable>> allOpenables = new HashMap<IRubyProject, ArrayList<IOpenable>>();
IRubyElement[] 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++) {
IRubyElement root = roots[i];
IRubyProject javaProject = root.getRubyProject();
ArrayList<IOpenable> openables = allOpenables.get(javaProject);
if (openables == null) {
openables = new ArrayList<IOpenable>();
allOpenables.put(javaProject, openables);
}
switch (root.getElementType()) {
case IRubyElement.RUBY_PROJECT :
injectAllOpenablesForRubyProject((IRubyProject) root, openables);
break;
case IRubyElement.SOURCE_FOLDER_ROOT :
injectAllOpenablesForSourceFolderRoot((ISourceFolderRoot) root, openables);
break;
case IRubyElement.SOURCE_FOLDER :
injectAllOpenablesForSourceFolder((ISourceFolder) root, openables);
break;
case IRubyElement.SCRIPT :
openables.add((IRubyScript) root);
break;
case IRubyElement.TYPE :
IType type = (IType)root;
openables.add(type.getRubyScript());
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 injectAllOpenablesForRubyProject(
IRubyProject project,
ArrayList<IOpenable> openables) {
try {
ISourceFolderRoot[] devPathRoots =
((RubyProject) project).getSourceFolderRoots();
if (devPathRoots == null) {
return;
}
for (int j = 0; j < devPathRoots.length; j++) {
ISourceFolderRoot root = devPathRoots[j];
injectAllOpenablesForSourceFolderRoot(root, openables);
}
} catch (RubyModelException e) {
// ignore
}
}
/**
* Adds all of the openables defined within this package fragment to the
* list.
*/
private void injectAllOpenablesForSourceFolder(
ISourceFolder packFrag,
ArrayList<IOpenable> openables) {
try {
IRubyScript[] cus = packFrag.getRubyScripts();
for (int i = 0, length = cus.length; i < length; i++) {
openables.add(cus[i]);
}
} catch (RubyModelException e) {
// ignore
}
}
/**
* Adds all of the openables defined within this package fragment root to the
* list.
*/
private void injectAllOpenablesForSourceFolderRoot(
ISourceFolderRoot root,
ArrayList<IOpenable> openables) {
try {
IRubyElement[] packFrags = root.getChildren();
for (int k = 0; k < packFrags.length; k++) {
ISourceFolder packFrag = (ISourceFolder) packFrags[k];
injectAllOpenablesForSourceFolder(packFrag, openables);
}
} catch (RubyModelException e) {
return;
}
}
}