/*******************************************************************************
 * Copyright (c) 2000, 2017 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
 *
 * Contributors:
 *     xored software, Inc. - initial API and Implementation
 *     xored software, Inc. - Search All occurences bugfix,
 *     						  hilight only class name when class is in search results ( Alex Panchenko <alex@xored.com>)
 *******************************************************************************/
package org.eclipse.dltk.core.search.matching;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.dltk.ast.ASTNode;
import org.eclipse.dltk.ast.declarations.FieldDeclaration;
import org.eclipse.dltk.ast.declarations.MethodDeclaration;
import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
import org.eclipse.dltk.ast.declarations.TypeDeclaration;
import org.eclipse.dltk.compiler.env.INameEnvironment;
import org.eclipse.dltk.compiler.env.ISourceType;
import org.eclipse.dltk.compiler.env.lookup.Scope;
import org.eclipse.dltk.compiler.util.SimpleLookupTable;
import org.eclipse.dltk.compiler.util.SimpleSet;
import org.eclipse.dltk.core.DLTKCore;
import org.eclipse.dltk.core.DLTKLanguageManager;
import org.eclipse.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.core.IField;
import org.eclipse.dltk.core.IMember;
import org.eclipse.dltk.core.IMethod;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IModelStatusConstants;
import org.eclipse.dltk.core.IParent;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISearchableEnvironment;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.IType;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.search.BasicSearchEngine;
import org.eclipse.dltk.core.search.FieldDeclarationMatch;
import org.eclipse.dltk.core.search.FieldReferenceMatch;
import org.eclipse.dltk.core.search.IDLTKSearchScope;
import org.eclipse.dltk.core.search.IMatchLocatorParser;
import org.eclipse.dltk.core.search.MethodDeclarationMatch;
import org.eclipse.dltk.core.search.MethodReferenceMatch;
import org.eclipse.dltk.core.search.SearchDocument;
import org.eclipse.dltk.core.search.SearchMatch;
import org.eclipse.dltk.core.search.SearchParticipant;
import org.eclipse.dltk.core.search.SearchPattern;
import org.eclipse.dltk.core.search.SearchRequestor;
import org.eclipse.dltk.core.search.TypeDeclarationMatch;
import org.eclipse.dltk.core.search.TypeReferenceMatch;
import org.eclipse.dltk.core.search.index.Index;
import org.eclipse.dltk.internal.compiler.env.AccessRestriction;
import org.eclipse.dltk.internal.compiler.impl.ITypeRequestor;
import org.eclipse.dltk.internal.compiler.lookup.LookupEnvironment;
import org.eclipse.dltk.internal.compiler.lookup.SourceModuleScope;
import org.eclipse.dltk.internal.core.ArchiveProjectFragment;
import org.eclipse.dltk.internal.core.ModelElement;
import org.eclipse.dltk.internal.core.ModelManager;
import org.eclipse.dltk.internal.core.ModelStatus;
import org.eclipse.dltk.internal.core.NameLookup;
import org.eclipse.dltk.internal.core.Openable;
import org.eclipse.dltk.internal.core.ScriptProject;
import org.eclipse.dltk.internal.core.SourceModule;
import org.eclipse.dltk.internal.core.SourceRefElement;
import org.eclipse.dltk.internal.core.search.IndexQueryRequestor;
import org.eclipse.dltk.internal.core.search.matching.AndPattern;
import org.eclipse.dltk.internal.core.search.matching.InternalSearchPattern;
import org.eclipse.dltk.internal.core.search.matching.MatchingNodeSet;
import org.eclipse.dltk.internal.core.search.matching.OrPattern;
import org.eclipse.dltk.internal.core.util.HandleFactory;
import org.eclipse.dltk.internal.core.util.Util;

public class MatchLocator implements IMatchLocator, ITypeRequestor {
	public static final int MAX_AT_ONCE;
	static {
		long maxMemory = Runtime.getRuntime().maxMemory();
		int ratio = (int) Math.round(((double) maxMemory) / (64 * 0x100000));
		switch (ratio) {
		case 0:
		case 1:
			MAX_AT_ONCE = 100;
			break;
		case 2:
			MAX_AT_ONCE = 200;
			break;
		case 3:
			MAX_AT_ONCE = 300;
			break;
		default:
			MAX_AT_ONCE = 400;
			break;
		}
	}

	// permanent state
	public SearchPattern pattern;

	public PatternLocator patternLocator;

	public int matchContainer;

	public SearchRequestor requestor;

	public IDLTKSearchScope scope;

	private IProgressMonitor progressMonitor;

	public org.eclipse.dltk.core.ISourceModule[] workingCopies;

	private HandleFactory handleFactory;

	// cache of all super type names if scope is hierarchy scope
	public char[][][] allSuperTypeNames;

	// the following is valid for the current project
	public IMatchLocatorParser parser;

	// private Parser basicParser;
	public INameEnvironment nameEnvironment;

	public NameLookup nameLookup;

	public LookupEnvironment lookupEnvironment;

	// management of PossibleMatch to be processed
	public int numberOfMatches; // (numberOfMatches - 1) is the last unit in

	// matchesToProcess
	public PossibleMatch[] matchesToProcess;

	public PossibleMatch currentPossibleMatch;

	/*
	 * Time spent in the IJavaSearchResultCollector
	 */
	public long resultCollectorTime = 0;

	// Progress information
	protected int progressStep;

	protected int progressWorked;

	// Binding resolution and cache
	protected SourceModuleScope unitScope;

	protected SimpleLookupTable bindings;

	// Cache for handles
	private HashSet handles;

	static public class WrappedCoreException extends RuntimeException {
		private static final long serialVersionUID = 8354329870126121212L; // backward

		// compatible
		public CoreException coreException;

		public WrappedCoreException(CoreException coreException) {
			this.coreException = coreException;
		}
	}

	public static void setFocus(InternalSearchPattern pattern,
			IModelElement focus) {
		pattern.focus = focus;
		if (pattern instanceof OrPattern) {
			for (SearchPattern child : ((OrPattern) pattern).getPatterns()) {
				child.focus = focus;
			}
		}
	}

	public static SearchPattern createAndPattern(
			final SearchPattern leftPattern, final SearchPattern rightPattern) {
		Assert.isNotNull(leftPattern.getToolkit());
		Assert.isTrue(
				leftPattern.getToolkit().equals(rightPattern.getToolkit()));
		return new AndPattern(0/* no kind */, 0/* no rule */,
				leftPattern.getToolkit()) {
			SearchPattern current = leftPattern;

			@Override
			public SearchPattern currentPattern() {
				return this.current;
			}

			@Override
			public boolean hasNextQuery() {
				if (this.current == leftPattern) {
					this.current = rightPattern;
					return true;
				}
				return false;
			}

			@Override
			public void resetQuery() {
				this.current = leftPattern;
			}
		};
	}

	/**
	 * Query a given index for matching entries. Assumes the sender has opened
	 * the index and will close when finished.
	 */
	public static void findIndexMatches(InternalSearchPattern pattern,
			Index index, IndexQueryRequestor requestor,
			SearchParticipant participant, IDLTKSearchScope scope,
			IProgressMonitor monitor) throws IOException {
		pattern.findIndexMatches(index, requestor, participant, scope, monitor);
	}

	public static IModelElement getProjectOrArchive(IModelElement element) {
		while (!(element instanceof IScriptProject)
				&& !(element instanceof ArchiveProjectFragment)) {
			element = element.getParent();
		}
		return element;
	}

	public static boolean isPolymorphicSearch(InternalSearchPattern pattern) {
		return pattern.isPolymorphicSearch();
	}

	public static IModelElement projectOrArchiveFocus(
			InternalSearchPattern pattern) {
		return pattern == null || pattern.focus == null ? null
				: getProjectOrArchive(pattern.focus);
	}

	public MatchLocator() {
	}

	@Override
	public void initialize(SearchPattern pattern, IDLTKSearchScope scope) {
		this.pattern = pattern;
		this.patternLocator = PatternLocator.patternLocator(this.pattern,
				scope.getLanguageToolkit());
		this.matchContainer = this.patternLocator.matchContainer();
		this.scope = scope;
	}

	@Override
	public void setRequestor(SearchRequestor requestor) {
		this.requestor = requestor;
	}

	@Override
	public void setProgressMonitor(IProgressMonitor progressMonitor) {
		this.progressMonitor = progressMonitor;
	}

	/**
	 * Add an additional compilation unit into the loop -> build compilation
	 * unit declarations, their bindings and record their results.
	 */
	public void accept(ISourceModule sourceUnit,
			AccessRestriction accessRestriction) {
	}

	/**
	 * Add additional source types
	 */
	public void accept(ISourceType[] sourceTypes,
			AccessRestriction accessRestriction) {
	}

	/*
	 * / Computes the super type names of the focus type if any.
	 */
	protected char[][][] computeSuperTypeNames(IType focusType) {
		return null;
	}

	/**
	 * Creates an IMethod from the given method declaration and type.
	 */
	protected IModelElement createHandle(MethodDeclaration method,
			IModelElement parent) {
		// if (!(parent instanceof IType)) return parent;
		if (parent instanceof IType) {
			IType type = (IType) parent;
			return createMethodHandle(type, method.getName());
		} else if (parent instanceof ISourceModule) {
			return createMethodHandle((ISourceModule) parent, method.getName());
		}
		return null;
	}

	/**
	 * Creates an IMethod from the given method declaration and type.
	 */
	protected IModelElement createHandle(FieldDeclaration field,
			IModelElement parent) {
		// if (!(parent instanceof IType)) return parent;
		if (parent instanceof IType) {
			IType type = (IType) parent;
			return createFieldHandle(type, field.getName());
		} else if (parent instanceof ISourceModule) {
			return createFieldHandle((ISourceModule) parent, field.getName());
		}
		return null;
	}

	/*
	 * Create method handle. Store occurences for create handle to retrieve
	 * possible duplicate ones.
	 */
	protected IModelElement createMethodHandle(IType type, String methodName) {
		IMethod methodHandle = type.getMethod(methodName);
		resolveDuplicates(methodHandle);
		return methodHandle;
	}

	/**
	 * Increment the {@link SourceRefElement#occurrenceCount} until the
	 * specified handle is unique.
	 *
	 * @param handle
	 */
	protected void resolveDuplicates(IMember handle) {
		if (handle instanceof SourceRefElement) {
			while (this.handles.contains(handle)) {
				((SourceRefElement) handle).occurrenceCount++;
			}
			this.handles.add(handle);
		}
	}

	protected IModelElement createTypeHandle(IType parent, String name) {
		final IType typeHandle = parent.getType(name);
		resolveDuplicates(typeHandle);
		return typeHandle;
	}

	/*
	 * Create method handle. Store occurrences for create handle to retrieve
	 * possible duplicate ones.
	 */
	protected IModelElement createMethodHandle(ISourceModule module,
			String methodName) {

		IMethod methodHandle = module.getMethod(methodName);
		resolveDuplicates(methodHandle);
		return methodHandle;
	}

	/*
	 * Create method handle. Store occurences for create handle to retrieve
	 * possible duplicate ones.
	 */
	protected IModelElement createFieldHandle(IType type, String methodName) {
		IField fieldHandle = type.getField(methodName);
		resolveDuplicates(fieldHandle);
		return fieldHandle;
	}

	/*
	 * Create method handle. Store occurences for create handle to retrieve
	 * possible duplicate ones.
	 */
	protected IModelElement createFieldHandle(ISourceModule module,
			String methodName) {

		IField fieldHandle = module.getField(methodName);
		resolveDuplicates(fieldHandle);
		return fieldHandle;
	}

	/**
	 * Creates an IType from the given simple top level type name.
	 */
	protected IType createTypeHandle(String simpleTypeName) {
		Openable openable = this.currentPossibleMatch.openable;
		IType type = null;
		if (openable instanceof ISourceModule)
			type = ((ISourceModule) openable).getType(simpleTypeName);
		resolveDuplicates(type);
		return type;
	}

	/**
	 * Creates an IType from the given simple top level type name.
	 */
	protected ISourceModule createSourceModuleHandle() {
		Openable openable = this.currentPossibleMatch.openable;
		if (openable instanceof ISourceModule)
			return ((ISourceModule) openable);
		return null;
	}

	/**
	 * Creates an IType from the given simple top level type name.
	 */
	protected IMethod createMethodHandle(String simpleTypeName) {
		Openable openable = this.currentPossibleMatch.openable;
		IMethod method = null;
		if (openable instanceof ISourceModule)
			method = ((ISourceModule) openable).getMethod(simpleTypeName);
		resolveDuplicates(method);
		return method;
	}

	/**
	 * Creates an IType from the given simple top level type name.
	 */
	protected IField createFieldHandle(String simpleTypeName) {
		Openable openable = this.currentPossibleMatch.openable;
		IField field;
		if (openable instanceof ISourceModule) {
			field = ((SourceModule) openable).getField(simpleTypeName);
		} else {
			field = null;
		}
		resolveDuplicates(field);
		return field;
	}

	protected boolean encloses(IModelElement element) {
		return element != null && this.scope.encloses(element);
	}

	protected void getMethodBodies(ModuleDeclaration unit,
			MatchingNodeSet nodeSet) {

		try {
			this.parser.setNodeSet(nodeSet);
			this.parser.parseBodies(unit);
		} finally {
			this.parser.setNodeSet(null);
		}
	}

	/**
	 * Create a new parser for the given project, as well as a lookup
	 * environment.
	 *
	 * @since 2.0
	 */
	public void initialize(IScriptProject project, int possibleMatchSize)
			throws ModelException {
		// clean up name environment only if there are several possible match as
		// it is
		// reused
		// when only one possible match (bug 58581)
		if (this.nameEnvironment != null && possibleMatchSize != 1)
			this.nameEnvironment.cleanup();

		ISearchableEnvironment searchableEnvironment = ((ScriptProject) project)
				.newSearchableNameEnvironment(this.workingCopies);

		// if only one possible match, a file name environment costs too much,
		// so use the existing searchable environment which will populate the
		// scriptmodel
		// only for this possible match and its required types.

		this.nameEnvironment = possibleMatchSize == 1
				? (INameEnvironment) searchableEnvironment
				: null;// (INameEnvironment)

		this.lookupEnvironment = new LookupEnvironment(this, /*
																 * problemReporter,
																 */
				this.nameEnvironment);

		IDLTKLanguageToolkit tk = null;
		tk = DLTKLanguageManager.getLanguageToolkit(project);
		if (tk == null) {
			throw new ModelException(new ModelStatus(
					IModelStatusConstants.INVALID_PROJECT, project,
					Messages.MatchLocator_languageToolkitNotFoundForProject));
		}
		this.parser = DLTKLanguageManager.createMatchParser(tk.getNatureId(),
				this);

		// remember project's name lookup
		this.nameLookup = searchableEnvironment.getNameLookup();

		// initialize queue of units
		this.numberOfMatches = 0;
		this.matchesToProcess = new PossibleMatch[possibleMatchSize];
	}

	/**
	 * @since 2.0
	 */
	protected void locateMatches(IScriptProject scriptProject,
			PossibleMatch[] possibleMatches, int start, int length)
			throws CoreException {
		initialize(scriptProject, length);
		// create and resolve binding (equivalent to beginCompilation() in
		// Compiler)
		for (int i = start, maxUnits = start + length; i < maxUnits; i++) {
			PossibleMatch possibleMatch = possibleMatches[i];
			try {
				if (!parse(possibleMatch))
					continue;
				worked();
				process(possibleMatch);
				if (this.numberOfMatches > 0
						&& this.matchesToProcess[this.numberOfMatches
								- 1] == possibleMatch) {
					// forget last possible match as it was processed
					this.numberOfMatches--;
				}
			} finally {
				possibleMatch.cleanUp();
			}
		}
	}

	private boolean parse(PossibleMatch possibleMatch) {
		if (this.progressMonitor != null && this.progressMonitor.isCanceled())
			throw new OperationCanceledException();

		try {
			if (BasicSearchEngine.VERBOSE)
				System.out.println("Parsing " //$NON-NLS-1$
						+ possibleMatch.openable.toStringWithAncestors());

			this.parser.setNodeSet(possibleMatch.nodeSet);
			ModuleDeclaration parsedUnit = this.parser.parse(possibleMatch);
			if (parsedUnit != null) {

				// if (hasAlreadyDefinedType(parsedUnit)) return false; // skip
				// type has it is hidden so not visible
				getMethodBodies(parsedUnit, possibleMatch.nodeSet);

				// add the possibleMatch with its parsedUnit to matchesToProcess
				possibleMatch.parsedUnit = parsedUnit;
				int size = this.matchesToProcess.length;
				if (this.numberOfMatches == size)
					System.arraycopy(this.matchesToProcess, 0,
							this.matchesToProcess = new PossibleMatch[size == 0
									? 1
									: size * 2],
							0, this.numberOfMatches);
				this.matchesToProcess[this.numberOfMatches++] = possibleMatch;
			}
		} finally {
			this.parser.setNodeSet(null);
		}
		return true;
	}

	/**
	 * Locate the matches amongst the possible matches.
	 *
	 * @noreference This method is not intended to be referenced by clients.
	 */
	protected void locateMatches(IScriptProject scriptProject,
			PossibleMatchSet matchSet, int expected) throws CoreException {
		PossibleMatch[] possibleMatches = matchSet
				.getPossibleMatches(scriptProject.getProjectFragments());
		int length = possibleMatches.length;
		// increase progress from duplicate matches not stored in matchSet while
		// adding...
		if (this.progressMonitor != null && expected > length) {
			this.progressWorked += expected - length;
			this.progressMonitor.worked(expected - length);
		}
		// locate matches (processed matches are limited to avoid problem while
		// using Interpreter default memory heap size)
		for (int index = 0; index < length;) {
			int max = Math.min(MAX_AT_ONCE, length - index);
			locateMatches(scriptProject, possibleMatches, index, max);
			index += max;
		}
		this.patternLocator.clear();
	}

	/**
	 * Locate the matches in the given files and report them using the search
	 * requestor.
	 */
	@Override
	public void locateMatches(SearchDocument[] searchDocuments)
			throws CoreException {
		int docsLength = searchDocuments.length;
		if (BasicSearchEngine.VERBOSE) {
			System.out.println("Locating matches in documents ["); //$NON-NLS-1$
			for (int i = 0; i < docsLength; i++)
				System.out.println("\t" + searchDocuments[i]); //$NON-NLS-1$
			System.out.println("]"); //$NON-NLS-1$
		}
		// init infos for progress increasing
		int n = docsLength < 1000
				? Math.min(Math.max(docsLength / 200 + 1, 2), 4)
				: 5 * (docsLength / 1000);
		this.progressStep = docsLength < n ? 1 : docsLength / n; // step
		// should
		// not be 0
		this.progressWorked = 0;
		// extract working copies
		this.workingCopies = ModuleFactory.selectWorkingCopies(searchDocuments);
		ModelManager manager = ModelManager.getModelManager();
		this.bindings = new SimpleLookupTable();
		try {
			// optimize access to zip files during search operation
			manager.cacheZipFiles();
			// initialize handle factory (used as a cache of handles so as to
			// optimize space)
			if (this.handleFactory == null)
				this.handleFactory = new HandleFactory();
			final ModuleFactory moduleFactory = new ModuleFactory(handleFactory,
					this.scope);
			if (this.progressMonitor != null) {
				this.progressMonitor.beginTask("", searchDocuments.length); //$NON-NLS-1$
			}
			// initialize pattern for polymorphic search (ie. method reference
			// pattern)
			this.patternLocator.initializePolymorphicSearch(this);
			IScriptProject previousScriptProject = null;
			PossibleMatchSet matchSet = new PossibleMatchSet();
			Util.sort(searchDocuments, (a, b) -> ((SearchDocument) a).getPath()
					.compareTo(((SearchDocument) b).getPath()));
			int displayed = 0; // progress worked displayed
			final Set<String> previousPaths = new HashSet<>();
			for (int i = 0; i < docsLength; i++) {
				if (this.progressMonitor != null
						&& this.progressMonitor.isCanceled()) {
					throw new OperationCanceledException();
				}
				// skip duplicate paths
				SearchDocument searchDocument = searchDocuments[i];
				searchDocuments[i] = null; // free current document
				if (!previousPaths.add(searchDocument.getPath())) {
					worked();
					displayed++;
					continue;
				}
				final ISourceModule openable = moduleFactory
						.create(searchDocument);
				if (openable == null) {
					worked();
					displayed++;
					continue; // match is outside buildpath
				}
				// create new parser and lookup environment if this is a new
				// project
				IScriptProject scriptProject = openable.getScriptProject();
				IResource resource = openable.getResource();
				if (resource == null)
					resource = scriptProject.getProject(); // case of a file in
				// an external jar
				if (!scriptProject.equals(previousScriptProject)) {
					// locate matches in previous project
					if (previousScriptProject != null) {
						try {
							locateMatches(previousScriptProject, matchSet,
									i - displayed);
							displayed = i;
						} catch (ModelException e) {
							// problem with buildpath in this project -> skip it
							DLTKCore.error("error in locateMatches", e); //$NON-NLS-1$
						}
						matchSet.reset();
					}
					previousScriptProject = scriptProject;
				}
				matchSet.add(new PossibleMatch(this, resource, openable,
						searchDocument));
			}
			// last project
			if (previousScriptProject != null) {
				try {
					locateMatches(previousScriptProject, matchSet,
							docsLength - displayed);
				} catch (ModelException e) {
					// problem with buildpath in last project -> ignore
					DLTKCore.error("error in locateMatches", e); //$NON-NLS-1$
				}
			}
			if (this.progressMonitor != null)
				this.progressMonitor.done();
		} finally {
			if (this.nameEnvironment != null)
				this.nameEnvironment.cleanup();
			manager.flushZipFiles();
			this.bindings = null;
		}
	}

	private void worked() {
		if (this.progressMonitor != null) {
			this.progressWorked++;
			if ((this.progressWorked % this.progressStep) == 0)
				this.progressMonitor.worked(this.progressStep);
		}
	}

	public SearchMatch newDeclarationMatch(IModelElement element, int accuracy,
			int offset, int length) {
		SearchParticipant participant = getParticipant();
		IResource resource = this.currentPossibleMatch.resource;
		return newDeclarationMatch(element, accuracy, offset, length,
				participant, resource);
	}

	public SearchMatch newDeclarationMatch(IModelElement element, int accuracy,
			int offset, int length, SearchParticipant participant,
			IResource resource) {
		switch (element.getElementType()) {
		case IModelElement.TYPE:
			return new TypeDeclarationMatch(element, accuracy, offset, length,
					participant, resource);
		case IModelElement.FIELD:
			return new FieldDeclarationMatch(element, accuracy, offset, length,
					participant, resource);

		case IModelElement.METHOD:
			return new MethodDeclarationMatch(element, accuracy, offset, length,
					participant, resource);
		default:
			return null;
		}
	}

	public SearchMatch newFieldReferenceMatch(IModelElement enclosingElement,
			int accuracy, int offset, int length, ASTNode reference) {
		SearchParticipant participant = getParticipant();
		IResource resource = this.currentPossibleMatch.resource;
		boolean insideDocComment = false;
		boolean isReadAccess = false;
		boolean isWriteAccess = false;

		if (enclosingElement instanceof IParent
				&& reference instanceof FieldDeclaration) {
			IParent parent = (IParent) enclosingElement;
			IModelElement[] children;
			try {
				FieldDeclaration decl = (FieldDeclaration) reference;
				children = parent.getChildren();
				boolean found = false;
				for (int i = 0; i < children.length; i++) {
					if (children[i].getElementName().equals(decl.getName())
							&& children[i] instanceof IField) {
						enclosingElement = children[i];
						found = true;
						break;
					}
				}
				if (!found) {
					return null;
				}
			} catch (ModelException e) {
				return null;
			}
		}
		return new FieldReferenceMatch(enclosingElement, reference, accuracy,
				offset, length, isReadAccess, isWriteAccess, insideDocComment,
				participant, resource);
	}

	public SearchMatch newMethodReferenceMatch(IModelElement enclosingElement,
			int accuracy, int offset, int length, boolean isConstructor,
			boolean isSynthetic, ASTNode reference) {
		SearchParticipant participant = getParticipant();
		IResource resource = this.currentPossibleMatch.resource;
		return new MethodReferenceMatch(enclosingElement, accuracy, offset,
				length, isConstructor, isSynthetic, false, participant,
				resource, reference);
	}

	public TypeReferenceMatch newTypeReferenceMatch(
			IModelElement enclosingElement, int accuracy, int offset,
			int length, ASTNode reference) {
		SearchParticipant participant = getParticipant();
		IResource resource = this.currentPossibleMatch.resource;
		return new TypeReferenceMatch(enclosingElement, accuracy, offset,
				length, false, participant, resource);
	}

	public TypeReferenceMatch newTypeReferenceMatch(
			IModelElement enclosingElement, int accuracy, ASTNode reference) {
		return newTypeReferenceMatch(enclosingElement, accuracy,
				reference.sourceStart(),
				reference.sourceEnd() - reference.sourceStart() + 1, reference);
	}

	/*
	 * Process a compilation unit already parsed and build.
	 */
	protected void process(PossibleMatch possibleMatch) throws CoreException {
		this.currentPossibleMatch = possibleMatch;
		ModuleDeclaration unit = possibleMatch.parsedUnit;
		try {
			if (unit == null || unit.isEmpty()) {
				return;
			}
			reportMatching(unit);
		} finally {
			this.currentPossibleMatch = null;
		}
	}

	public SearchParticipant getParticipant() {
		return this.currentPossibleMatch.document.getParticipant();
	}

	protected void report(SearchMatch match) throws CoreException {
		long start = -1;
		if (BasicSearchEngine.VERBOSE) {
			start = System.currentTimeMillis();
			System.out.println("Reporting match"); //$NON-NLS-1$
			System.out.println("\tResource: " + match.getResource());//$NON-NLS-1$
			System.out.println("\tPositions: [offset=" + match.getOffset() //$NON-NLS-1$
					+ ", length=" + match.getLength() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
			try {
				ModelElement modelElement = (ModelElement) match.getElement();
				System.out.println("\tJava element: " //$NON-NLS-1$
						+ modelElement.toStringWithAncestors());
				if (!modelElement.exists())
					System.out.println(
							"\t\tWARNING: this element does NOT exist!"); //$NON-NLS-1$
			} catch (Exception e) {
				// it's just for debug purposes... ignore all exceptions in this
				// area
			}
			if (match instanceof TypeReferenceMatch) {
				try {
					TypeReferenceMatch typeRefMatch = (TypeReferenceMatch) match;
					ModelElement local = (ModelElement) typeRefMatch
							.getLocalElement();
					if (local != null) {
						System.out.println("\tLocal element: " //$NON-NLS-1$
								+ local.toStringWithAncestors());
					}
					IModelElement[] others = typeRefMatch.getOtherElements();
					if (others != null) {
						int length = others.length;
						if (length > 0) {
							System.out.println("\tOther elements:"); //$NON-NLS-1$
							for (int i = 0; i < length; i++) {
								ModelElement other = (ModelElement) others[i];
								System.out.println("\t\t- " //$NON-NLS-1$
										+ other.toStringWithAncestors());
							}
						}
					}
				} catch (Exception e) {
					// it's just for debug purposes... ignore all exceptions in
					// this area
				}
			}
			System.out.println(match.getAccuracy() == SearchMatch.A_ACCURATE
					? "\tAccuracy: EXACT_MATCH" //$NON-NLS-1$
					: "\tAccuracy: POTENTIAL_MATCH"); //$NON-NLS-1$
			System.out.print("\tRule: "); //$NON-NLS-1$
			if (match.isExact()) {
				System.out.println("EXACT"); //$NON-NLS-1$
			} else if (match.isEquivalent()) {
				System.out.println("EQUIVALENT"); //$NON-NLS-1$
			} else if (match.isErasure()) {
				System.out.println("ERASURE"); //$NON-NLS-1$
			} else {
				System.out.println("INVALID RULE"); //$NON-NLS-1$
			}
			System.out.println("\tRaw: " + match.isRaw()); //$NON-NLS-1$
		}
		if (this.requestor != null) {
			this.requestor.acceptSearchMatch(match);
		}
		if (BasicSearchEngine.VERBOSE)
			this.resultCollectorTime += System.currentTimeMillis() - start;
	}

	private void resolvePotentialMatches(MatchingNodeSet nodeSet) {
		Object[] nodes = nodeSet.possibleMatchingNodesSet.values;
		for (int i = 0, l = nodes.length; i < l; i++) {
			ASTNode node = (ASTNode) nodes[i];
			if (node != null) {
				nodeSet.addMatch(node, PatternLocator.ACCURATE_MATCH);
				/**
				 * FIXME originally it was
				 *
				 * <pre>
				 * nodeSet.addMatch(node,
				 * 		this.patternLocator.resolveLevel(node));
				 * </pre>
				 *
				 * but resolveLevel() are not ported
				 */
			}
		}
		nodeSet.possibleMatchingNodesSet = new SimpleSet(3);
		if (BasicSearchEngine.VERBOSE) {
			int size = nodeSet.matchingNodes == null ? 0
					: nodeSet.matchingNodes.elementSize;
			System.out.print("	- node set: accurate=" + size); //$NON-NLS-1$
			size = nodeSet.possibleMatchingNodesSet == null ? 0
					: nodeSet.possibleMatchingNodesSet.elementSize;
			System.out.println(", possible=" + size); //$NON-NLS-1$
		}
	}

	/**
	 * Visit the given resolved parse tree and report the nodes that match the
	 * search pattern.
	 */
	protected void reportMatching(ModuleDeclaration unit) throws CoreException {
		MatchingNodeSet nodeSet = this.currentPossibleMatch.nodeSet;

		if (BasicSearchEngine.VERBOSE) {
			System.out.println("Report matching: "); //$NON-NLS-1$
			int size = nodeSet.matchingNodes == null ? 0
					: nodeSet.matchingNodes.elementSize;
			System.out.print("	- node set: accurate=" + size); //$NON-NLS-1$
			size = nodeSet.possibleMatchingNodesSet == null ? 0
					: nodeSet.possibleMatchingNodesSet.elementSize;
			System.out.println(", possible=" + size); //$NON-NLS-1$

		}

		/*
		 * move the possible matching nodes that exactly match the search
		 * pattern to the matching nodes set
		 */
		resolvePotentialMatches(nodeSet);

		this.unitScope = null;
		if (nodeSet.matchingNodes.elementSize == 0)
			return; // no matching nodes were found
		this.handles = new HashSet();
		boolean matchedUnitContainer = (this.matchContainer
				& PatternLocator.COMPILATION_UNIT_CONTAINER) != 0;
		// report references in javadoc

		TypeDeclaration[] types = unit.getTypes();
		if (types != null) {
			for (int i = 0, l = types.length; i < l; i++) {
				if (nodeSet.matchingNodes.elementSize == 0)
					return; // reported all the matching nodes
				TypeDeclaration type = types[i];
				Integer level = (Integer) nodeSet.matchingNodes
						.removeKey(parser.processType(type));
				int accuracy = (level != null && matchedUnitContainer)
						? level.intValue()
						: -1;
				reportMatching(type, null, accuracy, nodeSet, 1);
			}
		}
		// Visit functions
		MethodDeclaration[] methods = unit.getFunctions();
		if (methods != null) {
			for (int i = 0, l = methods.length; i < l; i++) {
				if (nodeSet.matchingNodes.elementSize == 0)
					return; // reported all the matching nodes
				MethodDeclaration method = methods[i];
				Integer level = (Integer) nodeSet.matchingNodes
						.removeKey(parser.processMethod(method));
				int accuracy = (level != null && matchedUnitContainer)
						? level.intValue()
						: -1;
				reportMatching(unit, method, null, accuracy, nodeSet);
			}
		}
		// Visit global variables
		FieldDeclaration[] fields = unit.getVariables();
		if (fields != null) {
			for (int i = 0, l = fields.length; i < l; i++) {
				if (nodeSet.matchingNodes.elementSize == 0)
					return; // reported all the matching nodes
				FieldDeclaration method = fields[i];
				Integer level = (Integer) nodeSet.matchingNodes
						.removeKey(method);
				int accuracy = (level != null && matchedUnitContainer)
						? level.intValue()
						: -1;
				reportMatching(unit, method, null, accuracy, nodeSet);
			}
		}

		// references in this module
		ASTNode[] nodes = nodeSet.matchingNodes(unit.sourceStart(),
				unit.sourceEnd());
		if (nodes != null) {
			if ((this.matchContainer
					& PatternLocator.COMPILATION_UNIT_CONTAINER) != 0) {
				ISourceModule enclosingElement = createSourceModuleHandle();
				if (encloses(enclosingElement)) {
					for (int i = 0, l = nodes.length; i < l; i++) {
						ASTNode node = nodes[i];
						Integer level = (Integer) nodeSet.matchingNodes
								.removeKey(node);
						if (DLTKCore.DEBUG) {
							System.out.println(
									"TODO: Searching. Add scope support."); //$NON-NLS-1$
						}
						this.patternLocator.matchReportReference(node,
								enclosingElement, (Scope) null,
								level.intValue(), this);

					}
				}
			}
			for (int i = 0, l = nodes.length; i < l; i++)
				nodeSet.matchingNodes.removeKey(nodes[i]);
		}

		// Clear handle cache
		this.handles = null;
		this.bindings.removeKey(this.pattern);
	}

	/**
	 * type Visit the given type declaration and report the nodes that match
	 * exactly the search pattern (ie. the ones in the matching nodes set)
	 */
	protected void reportMatching(TypeDeclaration type, IModelElement parent,
			int accuracy, MatchingNodeSet nodeSet, int occurrenceCount)
			throws CoreException {
		// create type handle
		IModelElement enclosingElement = parent;
		if (enclosingElement == null) {
			enclosingElement = createTypeHandle(type.getName());
		} else if (enclosingElement instanceof IType) {
			enclosingElement = createTypeHandle((IType) parent, type.getName());
		} else if (enclosingElement instanceof IMember) {
			IMember member = (IMember) parent;
			enclosingElement = member.getType(type.getName(), occurrenceCount);
		}
		if (enclosingElement == null)
			return;
		boolean enclosesElement = encloses(enclosingElement);
		// report the type declaration
		if (accuracy > -1 && enclosesElement) {
			SearchMatch match = this.patternLocator.newDeclarationMatch(type,
					enclosingElement, accuracy, this);
			report(match);
		}
		boolean matchedClassContainer = (this.matchContainer
				& PatternLocator.CLASS_CONTAINER) != 0;

		// filter out element not in hierarchy scope
		if (DLTKCore.DEBUG) {
			System.out
					.println("TODO: Searching. add variable handling here..."); //$NON-NLS-1$
		}

		boolean typeInHierarchy = true;// type.binding == null ||

		// Visit methods
		MethodDeclaration[] methods = type.getMethods();
		if (methods != null) {
			if (nodeSet.matchingNodes.elementSize == 0)
				return; // end as all matching nodes were reported
			for (int i = 0, l = methods.length; i < l; i++) {
				MethodDeclaration method = methods[i];
				Integer level = (Integer) nodeSet.matchingNodes
						.removeKey(parser.processMethod(method));
				int value = (level != null && matchedClassContainer)
						? level.intValue()
						: -1;
				reportMatching(type, method, enclosingElement, value, true,
						nodeSet);
			}
		}
		// Visit types
		TypeDeclaration[] memberTypes = type.getTypes();
		if (memberTypes != null) {
			for (int i = 0, l = memberTypes.length; i < l; i++) {
				if (nodeSet.matchingNodes.elementSize == 0)
					return; // end as all matching nodes were reported
				TypeDeclaration memberType = memberTypes[i];
				Integer level = (Integer) nodeSet.matchingNodes
						.removeKey(parser.processType(memberType));
				int value = (level != null && matchedClassContainer)
						? level.intValue()
						: -1;
				reportMatching(memberType, enclosingElement, value, nodeSet, 1);
			}
		}

		// Visit variables
		FieldDeclaration[] fields = type.getVariables();
		if (fields != null) {
			for (int i = 0, l = fields.length; i < l; i++) {
				if (nodeSet.matchingNodes.elementSize == 0)
					return; // reported all the matching nodes
				FieldDeclaration field = fields[i];
				Integer level = (Integer) nodeSet.matchingNodes
						.removeKey(field);
				int value = (level != null && matchedClassContainer)
						? level.intValue()
						: -1;
				reportMatching(type, field, enclosingElement, value, true,
						nodeSet);
			}
		}

		// references in this type
		if (typeInHierarchy) {
			ASTNode[] nodes = nodeSet.matchingNodes(type.sourceStart(),
					type.sourceEnd());
			if (nodes != null) {
				if ((this.matchContainer
						& PatternLocator.METHOD_CONTAINER) != 0) {
					if (encloses(enclosingElement)) {
						for (int i = 0, l = nodes.length; i < l; i++) {
							ASTNode node = nodes[i];
							Integer level = (Integer) nodeSet.matchingNodes
									.removeKey(node);
							if (DLTKCore.DEBUG) {
								System.out.println(
										"TODO: Searching. Add scope support."); //$NON-NLS-1$
							}
							this.patternLocator.matchReportReference(node,
									enclosingElement, (Scope) null,
									level.intValue(), this);
						}
						return;
					}
				}
				for (int i = 0, l = nodes.length; i < l; i++)
					nodeSet.matchingNodes.removeKey(nodes[i]);
			}
		}
	}

	/**
	 * Visit the given method declaration and report the nodes that match
	 * exactly the search pattern (ie. the ones in the matching nodes set) Note
	 * that the method declaration has already been checked.
	 */
	protected void reportMatching(TypeDeclaration type,
			MethodDeclaration method, IModelElement parent, int accuracy,
			boolean typeInHierarchy, MatchingNodeSet nodeSet)
			throws CoreException {
		IModelElement enclosingElement = null;
		if (accuracy > -1) {
			enclosingElement = createHandle(method, parent);
			if (enclosingElement != null) { // skip if unable to find method
				if (encloses(enclosingElement)) {
					SearchMatch match = null;
					if (DLTKCore.DEBUG) {
						System.out
								.println("TODO: AST Add constructor support."); //$NON-NLS-1$
					}
					match = this.patternLocator.newDeclarationMatch(method,
							enclosingElement, accuracy, this);
					// }
					if (match != null) {
						report(match);
					}
				}
			}
		}

		// references in this method
		if (typeInHierarchy) {
			ASTNode[] nodes = nodeSet.matchingNodes(method.sourceStart(),
					method.sourceEnd());
			if (nodes != null) {
				if ((this.matchContainer
						& PatternLocator.CLASS_CONTAINER) != 0) {
					if (enclosingElement == null)
						enclosingElement = createHandle(method, parent);
					if (encloses(enclosingElement)) {
						for (int i = 0, l = nodes.length; i < l; i++) {
							ASTNode node = nodes[i];
							Integer level = (Integer) nodeSet.matchingNodes
									.removeKey(node);
							if (DLTKCore.DEBUG) {
								System.out.println(
										"TODO: Searching. Add scope support."); //$NON-NLS-1$
							}
							this.patternLocator.matchReportReference(node,
									enclosingElement, (Scope) null,
									level.intValue(), this);
						}
						return;
					}
				}
				for (int i = 0, l = nodes.length; i < l; i++)
					nodeSet.matchingNodes.removeKey(nodes[i]);
			}
		}
	}

	/**
	 * Visit the given method declaration and report the nodes that match
	 * exactly the search pattern (ie. the ones in the matching nodes set) Note
	 * that the method declaration has already been checked.
	 */
	protected void reportMatching(TypeDeclaration type, FieldDeclaration field,
			IModelElement parent, int accuracy, boolean typeInHierarchy,
			MatchingNodeSet nodeSet) throws CoreException {
		IModelElement enclosingElement = null;
		if (accuracy > -1) {
			enclosingElement = createHandle(field, parent);
			if (enclosingElement != null) { // skip if unable to find method
				if (encloses(enclosingElement)) {
					SearchMatch match = null;
					if (DLTKCore.DEBUG) {
						System.out
								.println("TODO: AST Add constructor support."); //$NON-NLS-1$
					}
					match = this.patternLocator.newDeclarationMatch(field,
							enclosingElement, accuracy, this);
					// }
					if (match != null) {
						report(match);
					}
				}
			}
		}

		// references in this method
		if (typeInHierarchy) {
			ASTNode[] nodes = nodeSet.matchingNodes(field.sourceStart(),
					field.sourceEnd());
			if (nodes != null) {
				if ((this.matchContainer
						& PatternLocator.CLASS_CONTAINER) != 0) {
					if (enclosingElement == null)
						enclosingElement = createHandle(field, parent);
					if (encloses(enclosingElement)) {
						for (int i = 0, l = nodes.length; i < l; i++) {
							ASTNode node = nodes[i];
							Integer level = (Integer) nodeSet.matchingNodes
									.removeKey(node);
							if (DLTKCore.DEBUG) {
								System.out.println(
										"TODO: Searching. Add scope support."); //$NON-NLS-1$
							}
							this.patternLocator.matchReportReference(node,
									enclosingElement, (Scope) null,
									level.intValue(), this);
						}
						return;
					}
				}
				for (int i = 0, l = nodes.length; i < l; i++)
					nodeSet.matchingNodes.removeKey(nodes[i]);
			}
		}
	}

	/**
	 * Visit the given method declaration and report the nodes that match
	 * exactly the search pattern (ie. the ones in the matching nodes set) Note
	 * that the method declaration has already been checked.
	 */
	protected void reportMatching(ModuleDeclaration module,
			FieldDeclaration field, IModelElement parent, int accuracy,
			MatchingNodeSet nodeSet) throws CoreException {
		IModelElement enclosingElement = null;
		if (accuracy > -1) {
			if (parent == null) {
				parent = createSourceModuleHandle();
			}
			enclosingElement = createHandle(field, parent);
			if (enclosingElement == null) {
				enclosingElement = createFieldHandle(field.getName());
			}
			if (enclosingElement != null) { // skip if unable to find method
				if (encloses(enclosingElement)) {
					SearchMatch match = null;
					if (DLTKCore.DEBUG) {
						System.out
								.println("TODO: AST Add constructor support."); //$NON-NLS-1$
					}
					match = this.patternLocator.newDeclarationMatch(field,
							enclosingElement, accuracy, this);
					// }
					if (match != null) {
						report(match);
					}
				}
			}
		}

		// references in this method
		ASTNode[] nodes = nodeSet.matchingNodes(field.sourceStart(),
				field.sourceEnd());
		if (nodes != null) {
			if (parent == null) {
				parent = createSourceModuleHandle();
			}
			if ((this.matchContainer & PatternLocator.METHOD_CONTAINER) != 0) {
				if (enclosingElement == null)
					enclosingElement = createHandle(field, parent);
				if (encloses(enclosingElement)) {
					for (int i = 0, l = nodes.length; i < l; i++) {
						ASTNode node = nodes[i];
						Integer level = (Integer) nodeSet.matchingNodes
								.removeKey(node);
						if (DLTKCore.DEBUG) {
							System.out.println(
									"TODO: Searching. Add scope support."); //$NON-NLS-1$
						}
						this.patternLocator.matchReportReference(node,
								enclosingElement, (Scope) null,
								level.intValue(), this);
					}
					return;
				}
			}
			for (int i = 0, l = nodes.length; i < l; i++)
				nodeSet.matchingNodes.removeKey(nodes[i]);
		}
	}

	protected void reportMatching(ModuleDeclaration module,
			MethodDeclaration method, IModelElement parent, int accuracy,
			MatchingNodeSet nodeSet) throws CoreException {
		IModelElement enclosingElement = null;
		if (accuracy > -1) {
			if (parent == null) {
				parent = createSourceModuleHandle();
			}
			enclosingElement = createHandle(method, parent);
			if (enclosingElement == null) {
				enclosingElement = createMethodHandle(method.getName());
			}
			if (enclosingElement != null) { // skip if unable to find method
				if (encloses(enclosingElement)) {
					SearchMatch match = null;
					if (DLTKCore.DEBUG) {
						System.out
								.println("TODO: AST Add constructor support."); //$NON-NLS-1$
					}
					match = this.patternLocator.newDeclarationMatch(method,
							enclosingElement, accuracy, this);
					// }
					if (match != null) {
						report(match);
					}
				}
			}
		}

		// references in this method
		ASTNode[] nodes = nodeSet.matchingNodes(method.sourceStart(),
				method.sourceEnd());
		if (nodes != null) {
			if (parent == null) {
				parent = createSourceModuleHandle();
			}
			if ((this.matchContainer & PatternLocator.METHOD_CONTAINER) != 0) {
				if (enclosingElement == null)
					enclosingElement = createHandle(method, parent);
				if (encloses(enclosingElement)) {
					for (int i = 0, l = nodes.length; i < l; i++) {
						ASTNode node = nodes[i];
						Integer level = (Integer) nodeSet.matchingNodes
								.removeKey(node);
						if (DLTKCore.DEBUG) {
							System.out.println(
									"TODO: Searching. Add scope support."); //$NON-NLS-1$
						}
						this.patternLocator.matchReportReference(node,
								enclosingElement, (Scope) null,
								level.intValue(), this);
					}
					return;
				}
			}
			for (int i = 0, l = nodes.length; i < l; i++)
				nodeSet.matchingNodes.removeKey(nodes[i]);
		}
	}

	protected IType findTypeFrom(IModelElement[] childs, String name,
			String parentName, char delimiter) {
		try {
			for (int i = 0; i < childs.length; ++i) {
				if (childs[i] instanceof IType) {
					IType type = (IType) childs[i];
					String qname = name + delimiter + type.getElementName();
					if (qname.equals(parentName)) {
						return type;
					}
					IType val = findTypeFrom(type.getChildren(), qname,
							parentName, delimiter);
					if (val != null) {
						return val;
					}
				}
			}
		} catch (ModelException e) {
			if (DLTKCore.DEBUG) {
				e.printStackTrace();
			}
		}
		return null;
	}

}
