/*******************************************************************************
* 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.HashMap;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.rubypeople.rdt.core.IType;
import org.rubypeople.rdt.core.RubyModelException;
import org.rubypeople.rdt.internal.core.RubyElement;
import org.rubypeople.rdt.internal.core.RubyProject;
public abstract class HierarchyBuilder {
/**
* The hierarchy being built.
*/
protected TypeHierarchy hierarchy;
/**
* A temporary cache of infos to handles to speed info
* to handle translation - it only contains the entries
* for the types in the region (in other words, it contains
* no supertypes outside the region).
*/
protected Map infoToHandle;
/*
* The dot-separated fully qualified name of the focus type, or null of none.
*/
protected String focusQualifiedName;
protected HierarchyResolver hierarchyResolver;
public HierarchyBuilder(TypeHierarchy hierarchy) throws RubyModelException {
this.hierarchy = hierarchy;
RubyProject project = (RubyProject) hierarchy.rubyProject();
IType focusType = hierarchy.getType();
org.rubypeople.rdt.core.IRubyScript unitToLookInside = focusType == null ? null : focusType.getRubyScript();
org.rubypeople.rdt.core.IRubyScript[] workingCopies = this.hierarchy.workingCopies;
org.rubypeople.rdt.core.IRubyScript[] unitsToLookInside;
if (unitToLookInside != null) {
int wcLength = workingCopies == null ? 0 : workingCopies.length;
if (wcLength == 0) {
unitsToLookInside = new org.rubypeople.rdt.core.IRubyScript[] {unitToLookInside};
} else {
unitsToLookInside = new org.rubypeople.rdt.core.IRubyScript[wcLength+1];
unitsToLookInside[0] = unitToLookInside;
System.arraycopy(workingCopies, 0, unitsToLookInside, 1, wcLength);
}
} else {
unitsToLookInside = workingCopies;
}
if (project != null) {
// SearchableEnvironment searchableEnvironment = project.newSearchableNameEnvironment(unitsToLookInside);
// this.nameLookup = searchableEnvironment.nameLookup;
this.hierarchyResolver =
new HierarchyResolver(
// searchableEnvironment,
project.getOptions(true),
this
);
// new DefaultProblemFactory());
}
this.infoToHandle = new HashMap(5);
this.focusQualifiedName = focusType == null ? null : focusType.getFullyQualifiedName();
}
public abstract void build(boolean computeSubtypes)
throws RubyModelException, CoreException;
/**
* Connect the supplied type to its superclass & superinterfaces.
* The superclass & superinterfaces are the identical binary or source types as
* supplied by the name environment.
*/
public void connect(
IType typeHandle,
IType superclassHandle,
IType[] superinterfaceHandles) {
/*
* Temporary workaround for 1G2O5WK: ITPJCORE:WINNT - NullPointerException when selecting "Show in Type Hierarchy" for a inner class
*/
if (typeHandle == null)
return;
if (TypeHierarchy.DEBUG) {
System.out.println(
"Connecting: " + ((RubyElement) typeHandle).toStringWithAncestors()); //$NON-NLS-1$
System.out.println(
" to superclass: " //$NON-NLS-1$
+ (superclassHandle == null
? "<None>" //$NON-NLS-1$
: ((RubyElement) superclassHandle).toStringWithAncestors()));
System.out.print(" and superinterfaces:"); //$NON-NLS-1$
if (superinterfaceHandles == null || superinterfaceHandles.length == 0) {
System.out.println(" <None>"); //$NON-NLS-1$
} else {
System.out.println();
for (int i = 0, length = superinterfaceHandles.length; i < length; i++) {
if (superinterfaceHandles[i] == null) continue;
System.out.println(
" " + ((RubyElement) superinterfaceHandles[i]).toStringWithAncestors()); //$NON-NLS-1$
}
}
}
// now do the caching
if (typeHandle.isModule()) {
this.hierarchy.addModule(typeHandle);
} else {
if (superclassHandle == null) {
this.hierarchy.addRootClass(typeHandle);
} else {
this.hierarchy.cacheSuperclass(typeHandle, superclassHandle);
}
}
if (superinterfaceHandles == null) {
superinterfaceHandles = TypeHierarchy.NO_TYPE;
}
this.hierarchy.cacheSuperModules(typeHandle, superinterfaceHandles);
// record flags
this.hierarchy.cacheFlags(typeHandle, /*type.getModifiers()*/ 0 );
}
protected IType getType() {
return this.hierarchy.getType();
}
/**
* Configure this type hierarchy by computing the supertypes only.
*/
protected void buildSupertypes() {
IType focusType = this.getType();
if (focusType == null)
return;
// get generic type from focus type
// IGenericType type;
// try {
// type = (IGenericType) ((JavaElement) focusType).getElementInfo();
// } catch (JavaModelException e) {
// // if the focus type is not present, or if cannot get workbench path
// // we cannot create the hierarchy
// return;
// }
//NB: no need to set focus type on hierarchy resolver since no other type is injected
// in the hierarchy resolver, thus there is no need to check that a type is
// a sub or super type of the focus type.
this.hierarchyResolver.resolve(focusType);
// Add focus if not already in (case of a type with no explicit super type)
if (!this.hierarchy.contains(focusType)) {
this.hierarchy.addRootClass(focusType);
}
}
protected void worked(IProgressMonitor monitor, int work) {
if (monitor != null) {
if (monitor.isCanceled()) {
throw new OperationCanceledException();
} else {
monitor.worked(work);
}
}
}
}