/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 * 
 * SPDX-License-Identifier: EPL-2.0
 *
 *******************************************************************************/
package org.eclipse.dltk.internal.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.dltk.compiler.CharOperation;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.IBuildpathEntry;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IProjectFragment;
import org.eclipse.dltk.core.IScriptFolder;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.IType;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.environment.EnvironmentPathUtils;
import org.eclipse.dltk.internal.compiler.env.AccessRestriction;
import org.eclipse.dltk.internal.compiler.env.AccessRuleSet;
import org.eclipse.dltk.internal.core.util.HashtableOfArrayToObject;
import org.eclipse.dltk.internal.core.util.Messages;
import org.eclipse.dltk.internal.core.util.Util;

/**
 * A <code>NameLookup</code> provides name resolution within a Script project.
 * The name lookup facility uses the project's classpath to prioritize the order
 * in which package fragments are searched when resolving a name.
 * 
 * <p>
 * Name lookup only returns a handle when the named element actually exists in
 * the model; otherwise <code>null</code> is returned.
 * 
 * <p>
 * There are two logical sets of methods within this interface. Methods which
 * start with <code>find*</code> are intended to be convenience methods for
 * quickly finding an element within another element; for instance, for finding
 * a class within a package. The other set of methods all begin with
 * <code>seek*</code>. These methods do comprehensive searches of the
 * <code>IScriptProject</code> returning hits in real time through an
 * <code>IModelElementRequestor</code>.
 * 
 */
public class NameLookup {
	public static class Answer {
		public IType type;
		AccessRestriction restriction;

		Answer(IType type, AccessRestriction restriction) {
			this.type = type;
			this.restriction = restriction;
		}

		public boolean ignoreIfBetter() {
			return this.restriction != null
					&& this.restriction.ignoreIfBetter();
		}

		/*
		 * Returns whether this answer is better than the other awswer.
		 * (accessible is better than discouraged, which is better than
		 * non-accessible)
		 */
		public boolean isBetter(Answer otherAnswer) {
			if (otherAnswer == null)
				return true;
			if (this.restriction == null)
				return true;
			return otherAnswer.restriction != null
					&& this.restriction.getProblemId() < otherAnswer.restriction
							.getProblemId();
		}
	}

	/*
	 * Accept flag for all kinds of types
	 */

	public static boolean VERBOSE = DLTKCore.VERBOSE_SEARCH_NAMELOOKUP;

	private static final IType[] NO_TYPES = {};

	public static final int ACCEPT_ALL = 0;

	/**
	 * The <code>IScriptFolderRoot</code>'s associated with the buildpath of
	 * this NameLookup facility's project.
	 */
	protected IProjectFragment[] projectFragments;

	/**
	 * Table that maps package names to lists of package fragment roots that
	 * contain such a package known by this name lookup facility. To allow > 1
	 * package fragment with the same name, values are arrays of package
	 * fragment roots ordered as they appear on the buildpath. Note if the list
	 * is of size 1, then the IScriptFolderRoot object replaces the array.
	 */
	protected HashtableOfArrayToObject scriptFolders;

	/*
	 * A set of names (String[]) that are known to be package names. Value is
	 * not null for known package.
	 */
	protected HashtableOfArrayToObject isPackageCache;

	/**
	 * Reverse map from root path to corresponding resolved CP entry (so as to
	 * be able to figure inclusion/exclusion rules)
	 */
	protected Map rootToResolvedEntries;

	/**
	 * A map from package handles to a map from type name to an IType or an
	 * IType[]. Allows working copies to take precedence over compilation units.
	 */
	protected HashMap typesInWorkingCopies;

	public long timeSpentInSeekTypesInSourcePackage = 0;
	public long timeSpentInSeekTypesInBinaryPackage = 0;

	public NameLookup(IProjectFragment[] ProjectFragments,
			HashtableOfArrayToObject ScriptFolders,
			HashtableOfArrayToObject isPackage, ISourceModule[] workingCopies,
			Map rootToResolvedEntries) {
		long start = -1;
		if (VERBOSE) {
			Util.verbose(" BUILDING NameLoopkup"); //$NON-NLS-1$
			Util.verbose(" -> pkg roots size: " + (ProjectFragments == null ? 0 : ProjectFragments.length)); //$NON-NLS-1$
			Util.verbose(" -> pkgs size: " + (ScriptFolders == null ? 0 : ScriptFolders.size())); //$NON-NLS-1$
			Util.verbose(" -> working copy size: " + (workingCopies == null ? 0 : workingCopies.length)); //$NON-NLS-1$
			start = System.currentTimeMillis();
		}
		this.projectFragments = ProjectFragments;
		if (workingCopies == null) {
			this.scriptFolders = ScriptFolders;
			this.isPackageCache = isPackage;
		} else {
			// clone tables as we're adding packages from working copies
			try {
				this.scriptFolders = (HashtableOfArrayToObject) ScriptFolders
						.clone();
				this.isPackageCache = (HashtableOfArrayToObject) isPackage
						.clone();
			} catch (CloneNotSupportedException e1) {
				// ignore (implementation of HashtableOfArrayToObject supports
				// cloning)
			}
			this.typesInWorkingCopies = new HashMap();
			for (int i = 0, length = workingCopies.length; i < length; i++) {
				ISourceModule workingCopy = workingCopies[i];
				IScriptFolder pkg = (IScriptFolder) workingCopy.getParent();
				HashMap typeMap = (HashMap) this.typesInWorkingCopies.get(pkg);
				if (typeMap == null) {
					typeMap = new HashMap();
					this.typesInWorkingCopies.put(pkg, typeMap);
				}
				try {
					IType[] types = workingCopy.getTypes();
					int typeLength = types.length;
					if (typeLength == 0) {
						String typeName = workingCopy.getElementName();
						typeMap.put(typeName, NO_TYPES);
					} else {
						for (int j = 0; j < typeLength; j++) {
							IType type = types[j];
							String typeName = type.getElementName();
							Object existing = typeMap.get(typeName);
							if (existing == null) {
								typeMap.put(typeName, type);
							} else if (existing instanceof IType) {
								typeMap.put(typeName, new IType[] {
										(IType) existing, type });
							} else {
								IType[] existingTypes = (IType[]) existing;
								int existingTypeLength = existingTypes.length;
								System.arraycopy(
										existingTypes,
										0,
										existingTypes = new IType[existingTypeLength + 1],
										0, existingTypeLength);
								existingTypes[existingTypeLength] = type;
								typeMap.put(typeName, existingTypes);
							}
						}
					}
				} catch (ModelException e) {
					// working copy doesn't exist -> ignore
				}

				// add root of package fragment to cache
				IProjectFragment root = (IProjectFragment) pkg.getParent();
				IPath pkgPath = pkg.getPath().removeFirstSegments(
						root.getPath().segmentCount());
				String[] pkgName = pkgPath.segments();
				Object existing = this.scriptFolders.get(pkgName);
				if (existing == null) {
					this.scriptFolders.put(pkgName, root);
					// cache whether each package and its including packages
					// (see
					// https://bugs.eclipse.org/bugs/show_bug.cgi?id=119161)
					// are actual packages
					ProjectElementInfo.addNames(pkgName, this.isPackageCache);
				} else {
					if (existing instanceof IProjectFragment) {
						if (!existing.equals(root))
							this.scriptFolders
									.put(pkgName, new IProjectFragment[] {
											(IProjectFragment) existing, root });
					} else {
						IProjectFragment[] roots = (IProjectFragment[]) existing;
						int rootLength = roots.length;
						boolean containsRoot = false;
						for (int j = 0; j < rootLength; j++) {
							if (roots[j].equals(root)) {
								containsRoot = true;
								break;
							}
						}
						if (containsRoot) {
							System.arraycopy(
									roots,
									0,
									roots = new IProjectFragment[rootLength + 1],
									0, rootLength);
							roots[rootLength] = root;
							this.scriptFolders.put(pkgName, roots);
						}
					}
				}
			}
		}

		this.rootToResolvedEntries = rootToResolvedEntries;
		if (VERBOSE) {
			Util.verbose(" -> spent: " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	/**
	 * Returns true if:
	 * <ul>
	 * <li>the given type is an existing class and the flag's
	 * <code>ACCEPT_CLASSES</code> bit is on
	 * <li>the given type is an existing interface and the
	 * <code>ACCEPT_INTERFACES</code> bit is on
	 * <li>neither the <code>ACCEPT_CLASSES</code> or
	 * <code>ACCEPT_INTERFACES</code> bit is on
	 * </ul>
	 * Otherwise, false is returned.
	 */
	protected boolean acceptType(IType type, int acceptFlags,
			boolean isSourceType) {
		return true;
	}

	/**
	 * Finds every type in the project whose simple name matches the prefix,
	 * informing the requestor of each hit. The requestor is polled for
	 * cancellation at regular intervals.
	 * 
	 * <p>
	 * The <code>partialMatch</code> argument indicates partial matches should
	 * be considered.
	 */
	private void findAllTypes(String prefix, boolean partialMatch,
			int acceptFlags, IModelElementRequestor requestor) {
		int count = this.projectFragments.length;
		for (int i = 0; i < count; i++) {
			if (requestor.isCanceled())
				return;
			IProjectFragment root = this.projectFragments[i];
			IModelElement[] packages = null;
			try {
				packages = root.getChildren();
			} catch (ModelException npe) {
				continue; // the root is not present, continue;
			}
			if (packages != null) {
				for (int j = 0, packageCount = packages.length; j < packageCount; j++) {
					if (requestor.isCanceled())
						return;
					seekTypes(prefix, (IScriptFolder) packages[j],
							partialMatch, acceptFlags, requestor);
				}
			}
		}
	}

	/**
	 * Returns the <code>ISourceModule</code> which defines the type named
	 * <code>qualifiedTypeName</code>, or <code>null</code> if none exists. The
	 * domain of the search is bounded by the classpath of the
	 * <code>IScriptProject</code> this <code>NameLookup</code> was obtained
	 * from.
	 * <p>
	 * The name must be fully qualified (eg "java.lang.Object",
	 * "java.util.Hashtable$Entry")
	 */
	public ISourceModule findSourceModule(String qualifiedTypeName) {
		String[] pkgName = CharOperation.NO_STRINGS;
		String cuName = qualifiedTypeName;

		int index = qualifiedTypeName.lastIndexOf('.');
		if (index != -1) {
			pkgName = Util.splitOn('.', qualifiedTypeName, 0, index);
			cuName = qualifiedTypeName.substring(index + 1);
		}
		index = cuName.indexOf('$');
		if (index != -1) {
			cuName = cuName.substring(0, index);
		}
		Object value = this.scriptFolders.get(pkgName);
		if (value != null) {
			if (value instanceof IProjectFragment) {
				return findSourceModule(pkgName, cuName,
						(IProjectFragment) value);
			} else {
				IProjectFragment[] roots = (IProjectFragment[]) value;
				for (int i = 0; i < roots.length; i++) {
					IProjectFragment root = roots[i];
					ISourceModule cu = findSourceModule(pkgName, cuName, root);
					if (cu != null)
						return cu;
				}
			}
		}
		return null;
	}

	private IPath toPath(String pkgName[]) {
		IPath path = new Path(""); //$NON-NLS-1$
		for (int i = 0; i < pkgName.length; ++i) {
			path = path.append(pkgName[i]);
		}
		return path;
	}

	private ISourceModule findSourceModule(String[] pkgName, String cuName,
			IProjectFragment root) {
		if (!root.isArchive()) {
			IScriptFolder pkg = root.getScriptFolder(toPath(pkgName));
			try {
				ISourceModule[] cus = pkg.getSourceModules();
				for (int j = 0, length = cus.length; j < length; j++) {
					ISourceModule cu = cus[j];
					if (Util.equalsIgnoreExtension(cu.getElementName(), cuName))
						return cu;
				}
			} catch (ModelException e) {
				// pkg does not exist
				// -> try next package
			}
		}
		return null;
	}

	private static boolean equals(String s1, String s2) {
		return s1 == null ? s2 == null : s1.equals(s2);
	}

	/**
	 * Returns the package fragment whose path matches the given (absolute)
	 * path, or <code>null</code> if none exist. The domain of the search is
	 * bounded by the buildpath of the <code>IScriptProject</code> this
	 * <code>NameLookup</code> was obtained from. The path can be: - internal to
	 * the workbench: "/Project/src" - external to the workbench:
	 * "c:/jdk/classes.zip/java/lang"
	 */
	public IScriptFolder findScriptFolder(IPath path) {
		if (!path.isAbsolute()) {
			throw new IllegalArgumentException(Messages.path_mustBeAbsolute);
		}
		/*
		 * TODO (jerome) this code should rather use the package fragment map to
		 * find the candidate package, then check if the respective enclosing
		 * root maps to the one on this given IPath.
		 */
		IResource possibleFragment = ResourcesPlugin.getWorkspace().getRoot()
				.findMember(path);
		if (possibleFragment == null) {
			// external jar
			final boolean isFullPath = EnvironmentPathUtils.isFull(path);
			for (int i = 0; i < this.projectFragments.length; i++) {
				IProjectFragment root = this.projectFragments[i];
				if (!root.isExternal() || root.isBuiltin()) {
					continue;
				}
				IPath rootPath = root.getPath();
				if (!isFullPath) {
					rootPath = EnvironmentPathUtils.getLocalPath(rootPath);
				}
				int matchingCount = rootPath.matchingFirstSegments(path);
				if (matchingCount != 0
						&& equals(rootPath.getDevice(), path.getDevice())) {
					final String name = path.removeFirstSegments(matchingCount)
							.setDevice(null).makeRelative().toString();
					IModelElement[] list = null;
					try {
						list = root.getChildren();
					} catch (ModelException npe) {
						continue; // the package fragment root is not present;
					}
					int elementCount = list.length;
					for (int j = 0; j < elementCount; j++) {
						IScriptFolder scriptFolder = (IScriptFolder) list[j];
						if (nameMatches(name, scriptFolder, false)) {
							return scriptFolder;
						}
					}
				}
			}
		} else {
			IModelElement fromFactory = DLTKCore.create(possibleFragment);
			if (fromFactory == null) {
				return null;
			}
			switch (fromFactory.getElementType()) {
			case IModelElement.SCRIPT_FOLDER:
				return (IScriptFolder) fromFactory;
			case IModelElement.SCRIPT_PROJECT:
				// default package in a default root
				ScriptProject project = (ScriptProject) fromFactory;
				try {
					IBuildpathEntry entry = project.getBuildpathEntryFor(path);
					if (entry != null) {
						IProjectFragment root = project
								.getProjectFragment(project.getResource());
						Object defaultPkgRoot = this.scriptFolders
								.get(CharOperation.NO_STRINGS);
						if (defaultPkgRoot == null) {
							return null;
						}
						if (defaultPkgRoot instanceof IProjectFragment
								&& defaultPkgRoot.equals(root))
							return root.getScriptFolder(Path.EMPTY);
						else {
							IProjectFragment[] roots = (IProjectFragment[]) defaultPkgRoot;
							for (int i = 0; i < roots.length; i++) {
								if (roots[i].equals(root)) {
									return root.getScriptFolder(Path.EMPTY);
								}
							}
						}
					}
				} catch (ModelException e) {
					return null;
				}
				return null;
			case IModelElement.PROJECT_FRAGMENT:
				return ((IProjectFragment) fromFactory)
						.getScriptFolder(Path.EMPTY);
			}
		}
		return null;
	}

	/**
	 * Returns the package fragments whose name matches the given (qualified)
	 * name, or <code>null</code> if none exist.
	 * 
	 * The name can be: - empty: "" - qualified: "pack.pack1.pack2"
	 * 
	 * @param partialMatch
	 *            partial name matches qualify when <code>true</code>, only
	 *            exact name matches qualify when <code>false</code>
	 */
	public IScriptFolder[] findScriptFolders(String name, boolean partialMatch) {
		if (partialMatch) {
			String[] splittedName = Util.splitOn('.', name, 0, name.length());
			IScriptFolder[] oneFragment = null;
			ArrayList pkgs = null;
			Object[][] keys = this.scriptFolders.keyTable;
			for (int i = 0, length = keys.length; i < length; i++) {
				String[] pkgName = (String[]) keys[i];
				if (pkgName != null
						&& Util.startsWithIgnoreCase(pkgName, splittedName)) {
					Object value = this.scriptFolders.valueTable[i];
					if (value instanceof IProjectFragment) {
						IScriptFolder pkg = ((IProjectFragment) value)
								.getScriptFolder(toPath(pkgName));
						if (oneFragment == null) {
							oneFragment = new IScriptFolder[] { pkg };
						} else {
							if (pkgs == null) {
								pkgs = new ArrayList();
								pkgs.add(oneFragment[0]);
							}
							pkgs.add(pkg);
						}
					} else {
						IProjectFragment[] roots = (IProjectFragment[]) value;
						for (int j = 0, length2 = roots.length; j < length2; j++) {
							IProjectFragment root = roots[j];
							IScriptFolder pkg = root
									.getScriptFolder(toPath(pkgName));
							if (oneFragment == null) {
								oneFragment = new IScriptFolder[] { pkg };
							} else {
								if (pkgs == null) {
									pkgs = new ArrayList();
									pkgs.add(oneFragment[0]);
								}
								pkgs.add(pkg);
							}
						}
					}
				}
			}
			if (pkgs == null)
				return oneFragment;
			int resultLength = pkgs.size();
			IScriptFolder[] result = new IScriptFolder[resultLength];
			pkgs.toArray(result);
			return result;
		} else {
			String[] splittedName = Util.splitOn('.', name, 0, name.length());
			Object value = this.scriptFolders.get(splittedName);
			if (value == null)
				return null;
			if (value instanceof IProjectFragment) {
				return new IScriptFolder[] { ((IProjectFragment) value)
						.getScriptFolder(toPath(splittedName)) };
			} else {
				IProjectFragment[] roots = (IProjectFragment[]) value;
				IScriptFolder[] result = new IScriptFolder[roots.length];
				for (int i = 0; i < roots.length; i++) {
					result[i] = roots[i].getScriptFolder(toPath(splittedName));
				}
				return result;
			}
		}
	}

	/**
	 * Find type considering secondary types but without waiting for indexes. It
	 * means that secondary types may be not found under certain
	 * circumstances...
	 * 
	 * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=118789"
	 */
	public Answer findType(String typeName, String packageName,
			boolean partialMatch, int acceptFlags, boolean checkRestrictions) {
		return findType(typeName, packageName, partialMatch, acceptFlags,
				true/* consider secondary types */, false/*
														 * do NOT wait for
														 * indexes
														 */, checkRestrictions,
				null);
	}

	/**
	 * Find type. Considering secondary types and waiting for indexes depends on
	 * given corresponding parameters.
	 */
	public Answer findType(String typeName, String packageName,
			boolean partialMatch, int acceptFlags,
			boolean considerSecondaryTypes, boolean waitForIndexes,
			boolean checkRestrictions, IProgressMonitor monitor) {
		if (packageName == null || packageName.length() == 0) {
			packageName = IScriptFolder.DEFAULT_FOLDER_NAME;
		} else if (typeName.length() > 0
				&& Character.isLowerCase(typeName.charAt(0))) {
			// see if this is a known package and not a type
			if (findScriptFolders(packageName + "." + typeName, false) != null)return null; //$NON-NLS-1$
		}

		// Look for concerned package fragments
		ModelElementRequestor elementRequestor = new ModelElementRequestor();
		seekScriptFolders(packageName, false, elementRequestor);
		IScriptFolder[] packages = elementRequestor.getScriptFolders();

		// Try to find type in package fragments list
		IType type = null;
		int length = packages.length;
		HashSet projects = null;
		IScriptProject scriptProject = null;
		Answer suggestedAnswer = null;
		for (int i = 0; i < length; i++) {
			type = findType(typeName, packages[i], partialMatch, acceptFlags);
			if (type != null) {
				AccessRestriction accessRestriction = null;
				if (checkRestrictions) {
					accessRestriction = getViolatedRestriction(typeName,
							packageName, type, accessRestriction);
				}
				Answer answer = new Answer(type, accessRestriction);
				if (!answer.ignoreIfBetter()) {
					if (answer.isBetter(suggestedAnswer))
						return answer;
				} else if (answer.isBetter(suggestedAnswer))
					// remember suggestion and keep looking
					suggestedAnswer = answer;
			} else if (suggestedAnswer == null && considerSecondaryTypes) {
				if (scriptProject == null) {
					scriptProject = packages[i].getScriptProject();
				} else if (projects == null) {
					if (!scriptProject.equals(packages[i].getScriptProject())) {
						projects = new HashSet(3);
						projects.add(scriptProject);
						projects.add(packages[i].getScriptProject());
					}
				} else {
					projects.add(packages[i].getScriptProject());
				}
			}
		}
		if (suggestedAnswer != null)
			// no better answer was found
			return suggestedAnswer;

		return type == null ? null : new Answer(type, null);
	}

	private AccessRestriction getViolatedRestriction(String typeName,
			String packageName, IType type, AccessRestriction accessRestriction) {
		IProjectFragment root = (IProjectFragment) type
				.getAncestor(IModelElement.PROJECT_FRAGMENT);
		BuildpathEntry entry = (BuildpathEntry) this.rootToResolvedEntries
				.get(root);
		if (entry != null) { // reverse map always contains resolved CP entry
			AccessRuleSet accessRuleSet = entry.getAccessRuleSet();
			if (accessRuleSet != null) {
				// TODO (philippe) improve char[] <-> String conversions to
				// avoid performing them on the fly
				char[][] packageChars = CharOperation.splitOn('.',
						packageName.toCharArray());
				char[] typeChars = typeName.toCharArray();
				accessRestriction = accessRuleSet
						.getViolatedRestriction(CharOperation.concatWith(
								packageChars, typeChars, '/'));
			}
		}
		return accessRestriction;
	}

	/**
	 * Returns the first type in the given package whose name matches the given
	 * (unqualified) name, or <code>null</code> if none exist. Specifying a
	 * <code>null</code> package will result in no matches. The domain of the
	 * search is bounded by the Script project from which this name lookup was
	 * obtained.
	 * 
	 * @param name
	 *            the name of the type to find
	 * @param pkg
	 *            the package to search
	 * @param partialMatch
	 *            partial name matches qualify when <code>true</code>, only
	 *            exact name matches qualify when <code>false</code>
	 * @param acceptFlags
	 *            a bit mask describing if classes, interfaces or both classes
	 *            and interfaces are desired results. If no flags are specified,
	 *            all types are returned.
	 * @param considerSecondaryTypes
	 *            flag to know whether secondary types has to be considered
	 *            during the search
	 * 
	 * @see #ACCEPT_CLASSES
	 * @see #ACCEPT_INTERFACES
	 * @see #ACCEPT_ENUMS
	 * @see #ACCEPT_ANNOTATIONS
	 */
	public IType findType(String name, IScriptFolder pkg, boolean partialMatch,
			int acceptFlags, boolean considerSecondaryTypes) {
		IType type = findType(name, pkg, partialMatch, acceptFlags);
		return type;
	}

	/**
	 * Returns the first type in the given package whose name matches the given
	 * (unqualified) name, or <code>null</code> if none exist. Specifying a
	 * <code>null</code> package will result in no matches. The domain of the
	 * search is bounded by the Script project from which this name lookup was
	 * obtained. <br>
	 * Note that this method does not find secondary types. <br>
	 * 
	 * @param name
	 *            the name of the type to find
	 * @param pkg
	 *            the package to search
	 * @param partialMatch
	 *            partial name matches qualify when <code>true</code>, only
	 *            exact name matches qualify when <code>false</code>
	 * @param acceptFlags
	 *            a bit mask describing if classes, interfaces or both classes
	 *            and interfaces are desired results. If no flags are specified,
	 *            all types are returned.
	 * 
	 * @see #ACCEPT_CLASSES
	 * @see #ACCEPT_INTERFACES
	 * @see #ACCEPT_ENUMS
	 * @see #ACCEPT_ANNOTATIONS
	 */
	public IType findType(String name, IScriptFolder pkg, boolean partialMatch,
			int acceptFlags) {
		if (pkg == null)
			return null;

		// Return first found (ignore duplicates).
		SingleTypeRequestor typeRequestor = new SingleTypeRequestor();
		seekTypes(name, pkg, partialMatch, acceptFlags, typeRequestor);
		return typeRequestor.getType();
	}

	/**
	 * Returns the type specified by the qualified name, or <code>null</code> if
	 * none exist. The domain of the search is bounded by the Script project
	 * from which this name lookup was obtained.
	 * 
	 * @param name
	 *            the name of the type to find
	 * @param partialMatch
	 *            partial name matches qualify when <code>true</code>, only
	 *            exact name matches qualify when <code>false</code>
	 * @param acceptFlags
	 *            a bit mask describing if classes, interfaces or both classes
	 *            and interfaces are desired results. If no flags are specified,
	 *            all types are returned.
	 * 
	 * @see #ACCEPT_CLASSES
	 * @see #ACCEPT_INTERFACES
	 * @see #ACCEPT_ENUMS
	 * @see #ACCEPT_ANNOTATIONS
	 */
	public IType findType(String name, boolean partialMatch, int acceptFlags) {
		NameLookup.Answer answer = findType(name, partialMatch, acceptFlags,
				false/* don't check restrictions */);
		return answer == null ? null : answer.type;
	}

	public Answer findType(String name, boolean partialMatch, int acceptFlags,
			boolean checkRestrictions) {
		return findType(name, partialMatch, acceptFlags, true/*
															 * consider
															 * secondary types
															 */, true/*
																	 * wait for
																	 * indexes
																	 */,
				checkRestrictions, null);
	}

	public Answer findType(String name, boolean partialMatch, int acceptFlags,
			boolean considerSecondaryTypes, boolean waitForIndexes,
			boolean checkRestrictions, IProgressMonitor monitor) {
		int index = name.lastIndexOf('.');
		String className = null, packageName = null;
		if (index == -1) {
			packageName = IScriptFolder.DEFAULT_FOLDER_NAME;
			className = name;
		} else {
			packageName = name.substring(0, index);
			className = name.substring(index + 1);
		}
		return findType(className, packageName, partialMatch, acceptFlags,
				considerSecondaryTypes, waitForIndexes, checkRestrictions,
				monitor);
	}

	private IType getMemberType(IType type, String name, int dot) {
		while (dot != -1) {
			int start = dot + 1;
			dot = name.indexOf('.', start);
			String typeName = name.substring(start, dot == -1 ? name.length()
					: dot);
			type = type.getType(typeName);
		}
		return type;
	}

	public boolean isPackage(String[] pkgName) {
		return this.isPackageCache.get(pkgName) != null;
	}

	/**
	 * Returns true if the given element's name matches the specified
	 * <code>searchName</code>, otherwise false.
	 * 
	 * <p>
	 * The <code>partialMatch</code> argument indicates partial matches should
	 * be considered. NOTE: in partialMatch mode, the case will be ignored, and
	 * the searchName must already have been lowercased.
	 */
	protected boolean nameMatches(String searchName, IModelElement element,
			boolean partialMatch) {
		if (partialMatch) {
			// partial matches are used in completion mode, thus case
			// insensitive mode
			return element.getElementName().toLowerCase()
					.startsWith(searchName);
		} else {
			return element.getElementName().equals(searchName);
		}
	}

	/**
	 * Returns true if the given cu's name matches the specified
	 * <code>searchName</code>, otherwise false.
	 * 
	 * <p>
	 * The <code>partialMatch</code> argument indicates partial matches should
	 * be considered. NOTE: in partialMatch mode, the case will be ignored, and
	 * the searchName must already have been lowercased.
	 */
	protected boolean nameMatches(String searchName, ISourceModule cu,
			boolean partialMatch) {
		if (partialMatch) {
			// partial matches are used in completion mode, thus case
			// insensitive mode
			return cu.getElementName().toLowerCase().startsWith(searchName);
		} else {
			return Util.equalsIgnoreExtension(cu.getElementName(), searchName);
		}
	}

	/**
	 * Notifies the given requestor of all package fragments with the given
	 * name. Checks the requestor at regular intervals to see if the requestor
	 * has canceled. The domain of the search is bounded by the
	 * <code>IScriptProject</code> this <code>NameLookup</code> was obtained
	 * from.
	 * 
	 * @param partialMatch
	 *            partial name matches qualify when <code>true</code>; only
	 *            exact name matches qualify when <code>false</code>
	 */
	public void seekScriptFolders(String name, boolean partialMatch,
			IModelElementRequestor requestor) {
		/*
		 * if (VERBOSE) { Util.verbose(" SEEKING PACKAGE FRAGMENTS");
		 * //$NON-NLS-1$ Util.verbose(" -> name: " + name); //$NON-NLS-1$
		 * Util.verbose(" -> partial match:" + partialMatch); //$NON-NLS-1$ }
		 */if (partialMatch) {
			String[] splittedName = Util.splitOn('.', name, 0, name.length());
			Object[][] keys = this.scriptFolders.keyTable;
			for (int i = 0, length = keys.length; i < length; i++) {
				if (requestor.isCanceled())
					return;
				String[] pkgName = (String[]) keys[i];
				if (pkgName != null
						&& Util.startsWithIgnoreCase(pkgName, splittedName)) {
					Object value = this.scriptFolders.valueTable[i];
					if (value instanceof IProjectFragment) {
						IProjectFragment root = (IProjectFragment) value;
						requestor.acceptScriptFolder(root
								.getScriptFolder(toPath(pkgName)));
					} else {
						IProjectFragment[] roots = (IProjectFragment[]) value;
						for (int j = 0, length2 = roots.length; j < length2; j++) {
							if (requestor.isCanceled())
								return;
							IProjectFragment root = roots[j];
							requestor.acceptScriptFolder(root
									.getScriptFolder(toPath(pkgName)));
						}
					}
				}
			}
		} else {
			String[] splittedName = Util.splitOn('.', name, 0, name.length());
			Object value = this.scriptFolders.get(splittedName);
			if (value instanceof IProjectFragment) {
				requestor.acceptScriptFolder(((IProjectFragment) value)
						.getScriptFolder(toPath(splittedName)));
			} else {
				IProjectFragment[] roots = (IProjectFragment[]) value;
				if (roots != null) {
					for (int i = 0, length = roots.length; i < length; i++) {
						if (requestor.isCanceled())
							return;
						IProjectFragment root = roots[i];
						requestor.acceptScriptFolder(root
								.getScriptFolder(toPath(splittedName)));
					}
				}
			}
		}
	}

	/**
	 * Notifies the given requestor of all types (classes and interfaces) in the
	 * given package fragment with the given (unqualified) name. Checks the
	 * requestor at regular intervals to see if the requestor has canceled. If
	 * the given package fragment is <code>null</code>, all types in the project
	 * whose simple name matches the given name are found.
	 * 
	 * @param name
	 *            The name to search
	 * @param pkg
	 *            The corresponding package fragment
	 * @param partialMatch
	 *            partial name matches qualify when <code>true</code>; only
	 *            exact name matches qualify when <code>false</code>
	 * @param acceptFlags
	 *            a bit mask describing if classes, interfaces or both classes
	 *            and interfaces are desired results. If no flags are specified,
	 *            all types are returned.
	 * @param requestor
	 *            The requestor that collects the result
	 * 
	 * @see #ACCEPT_CLASSES
	 * @see #ACCEPT_INTERFACES
	 * @see #ACCEPT_ENUMS
	 * @see #ACCEPT_ANNOTATIONS
	 */
	public void seekTypes(String name, IScriptFolder pkg, boolean partialMatch,
			int acceptFlags, IModelElementRequestor requestor) {
		/*
		 * if (VERBOSE) { Util.verbose(" SEEKING TYPES"); //$NON-NLS-1$
		 * Util.verbose(" -> name: " + name); //$NON-NLS-1$
		 * Util.verbose(" -> pkg: " + ((ModelElement)
		 * pkg).toStringWithAncestors()); //$NON-NLS-1$
		 * Util.verbose(" -> partial match:" + partialMatch); //$NON-NLS-1$ }
		 */
		String matchName = partialMatch ? name.toLowerCase() : name;
		if (pkg == null) {
			findAllTypes(matchName, partialMatch, acceptFlags, requestor);
			return;
		}
		IProjectFragment root = (IProjectFragment) pkg.getParent();
		try {

			// look in working copies first
			int firstDot = -1;
			String topLevelTypeName = null;
			int packageFlavor = root.getKind();
			if (this.typesInWorkingCopies != null
					|| packageFlavor == IProjectFragment.K_SOURCE) {
				firstDot = matchName.indexOf('.');
				if (!partialMatch)
					topLevelTypeName = firstDot == -1 ? matchName : matchName
							.substring(0, firstDot);
			}
			if (this.typesInWorkingCopies != null) {
				if (seekTypesInWorkingCopies(matchName, pkg, firstDot,
						partialMatch, topLevelTypeName, acceptFlags, requestor))
					return;
			}

			// look in model
			switch (packageFlavor) {
			case IProjectFragment.K_SOURCE:
				seekTypesInSourcePackage(matchName, pkg, firstDot,
						partialMatch, topLevelTypeName, acceptFlags, requestor);
				break;
			default:
				return;
			}
		} catch (ModelException e) {
			return;
		}
	}

	/**
	 * Performs type search in a source package.
	 */
	protected void seekTypesInSourcePackage(String name, IScriptFolder pkg,
			int firstDot, boolean partialMatch, String topLevelTypeName,
			int acceptFlags, IModelElementRequestor requestor) {

		long start = -1;
		if (VERBOSE)
			start = System.currentTimeMillis();
		try {
			if (!partialMatch) {
				try {
					IModelElement[] compilationUnits = pkg.getChildren();
					for (int i = 0, length = compilationUnits.length; i < length; i++) {
						if (requestor.isCanceled())
							return;
						IModelElement cu = compilationUnits[i];
						String cuName = cu.getElementName();
						int lastDot = cuName.lastIndexOf('.');
						if (lastDot != topLevelTypeName.length()
								|| !topLevelTypeName.regionMatches(0, cuName,
										0, lastDot))
							continue;
						IType type = ((ISourceModule) cu)
								.getType(topLevelTypeName);
						type = getMemberType(type, name, firstDot);
						if (acceptType(type, acceptFlags, true/* a source type */)) { // accept
							// type
							// checks
							// for
							// existence
							requestor.acceptType(type);
							break; // since an exact match was requested, no
							// other matching type can exist
						}
					}
				} catch (ModelException e) {
					// package doesn't exist -> ignore
				}
			} else {
				try {
					String cuPrefix = firstDot == -1 ? name : name.substring(0,
							firstDot);
					IModelElement[] compilationUnits = pkg.getChildren();
					for (int i = 0, length = compilationUnits.length; i < length; i++) {
						if (requestor.isCanceled())
							return;
						IModelElement cu = compilationUnits[i];
						if (!cu.getElementName().toLowerCase()
								.startsWith(cuPrefix))
							continue;
						try {
							IType[] types = ((ISourceModule) cu).getTypes();
							for (int j = 0, typeLength = types.length; j < typeLength; j++)
								seekTypesInTopLevelType(name, firstDot,
										types[j], requestor, acceptFlags);
						} catch (ModelException e) {
							// cu doesn't exist -> ignore
						}
					}
				} catch (ModelException e) {
					// package doesn't exist -> ignore
				}
			}
		} finally {
			if (VERBOSE)
				this.timeSpentInSeekTypesInSourcePackage += System
						.currentTimeMillis() - start;
		}
	}

	/**
	 * Notifies the given requestor of all types (classes and interfaces) in the
	 * given type with the given (possibly qualified) name. Checks the requestor
	 * at regular intervals to see if the requestor has canceled.
	 */
	protected boolean seekTypesInType(String prefix, int firstDot, IType type,
			IModelElementRequestor requestor, int acceptFlags) {
		IType[] types = null;
		try {
			types = type.getTypes();
		} catch (ModelException npe) {
			return false; // the enclosing type is not present
		}
		int length = types.length;
		if (length == 0)
			return false;

		String memberPrefix = prefix;
		boolean isMemberTypePrefix = false;
		if (firstDot != -1) {
			memberPrefix = prefix.substring(0, firstDot);
			isMemberTypePrefix = true;
		}
		for (int i = 0; i < length; i++) {
			if (requestor.isCanceled())
				return false;
			IType memberType = types[i];
			if (memberType.getElementName().toLowerCase()
					.startsWith(memberPrefix))
				if (isMemberTypePrefix) {
					String subPrefix = prefix.substring(firstDot + 1,
							prefix.length());
					return seekTypesInType(subPrefix, subPrefix.indexOf('.'),
							memberType, requestor, acceptFlags);
				} else {
					if (acceptType(memberType, acceptFlags, true/* a source type */)) {
						requestor.acceptMemberType(memberType);
						return true;
					}
				}
		}
		return false;
	}

	protected boolean seekTypesInTopLevelType(String prefix, int firstDot,
			IType topLevelType, IModelElementRequestor requestor,
			int acceptFlags) {
		if (!topLevelType.getElementName().toLowerCase().startsWith(prefix))
			return false;
		if (firstDot == -1) {
			if (acceptType(topLevelType, acceptFlags, true/* a source type */)) {
				requestor.acceptType(topLevelType);
				return true;
			}
		} else {
			return seekTypesInType(prefix, firstDot, topLevelType, requestor,
					acceptFlags);
		}
		return false;
	}

	/*
	 * Seeks the type with the given name in the map of types with precedence
	 * (coming from working copies) Return whether a type has been found.
	 */
	protected boolean seekTypesInWorkingCopies(String name, IScriptFolder pkg,
			int firstDot, boolean partialMatch, String topLevelTypeName,
			int acceptFlags, IModelElementRequestor requestor) {

		if (!partialMatch) {
			HashMap typeMap = (HashMap) (this.typesInWorkingCopies == null ? null
					: this.typesInWorkingCopies.get(pkg));
			if (typeMap != null) {
				Object object = typeMap.get(topLevelTypeName);
				if (object instanceof IType) {
					IType type = getMemberType((IType) object, name, firstDot);
					if (acceptType(type, acceptFlags, true/* a source type */)) {
						requestor.acceptType(type);
						return true; // don't continue with compilation unit
					}
				} else if (object instanceof IType[]) {
					if (object == NO_TYPES)
						return true; // all types where deleted -> type is
					// hidden
					IType[] topLevelTypes = (IType[]) object;
					for (int i = 0, length = topLevelTypes.length; i < length; i++) {
						if (requestor.isCanceled())
							return false;
						IType type = getMemberType(topLevelTypes[i], name,
								firstDot);
						if (acceptType(type, acceptFlags, true/* a source type */)) {
							requestor.acceptType(type);
							return true; // return the first one
						}
					}
				}
			}
		} else {
			HashMap typeMap = (HashMap) (this.typesInWorkingCopies == null ? null
					: this.typesInWorkingCopies.get(pkg));
			if (typeMap != null) {
				Iterator iterator = typeMap.values().iterator();
				while (iterator.hasNext()) {
					if (requestor.isCanceled())
						return false;
					Object object = iterator.next();
					if (object instanceof IType) {
						seekTypesInTopLevelType(name, firstDot, (IType) object,
								requestor, acceptFlags);
					} else if (object instanceof IType[]) {
						IType[] topLevelTypes = (IType[]) object;
						for (int i = 0, length = topLevelTypes.length; i < length; i++)
							seekTypesInTopLevelType(name, firstDot,
									topLevelTypes[i], requestor, acceptFlags);
					}
				}
			}
		}
		return false;
	}

}
