blob: 86b3302b3ae3f8315e00f52c7f4a29a88c5b4bc9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.core.indexsearch;
import java.io.IOException;
import java.util.*;
import java.util.Iterator;
import org.eclipse.core.resources.*;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
/**
* A <code>SearchEngine</code> searches for java elements following a search pattern.
* <p>
* This class may be instantiated; it is not intended to be subclassed.
*/
public class SearchEngine {
static class MyIndex implements IIndex {
private HashMap fMap= new HashMap();
public void addRef(String word, String path) {
System.err.println("Index.add: " + path + " " + word); //$NON-NLS-1$ //$NON-NLS-2$
HashMap words= (HashMap) fMap.get(path);
if (words == null) {
words= new HashMap();
fMap.put(path, words);
}
words.put(word, word);
}
public void remove(String path) {
System.err.println("Index.remove: " + path); //$NON-NLS-1$
fMap.remove(path);
}
public void queryPrefix(HashSet results, String w) {
Iterator iter= fMap.keySet().iterator();
while (iter.hasNext()) {
String path= (String) iter.next();
HashMap words= (HashMap) fMap.get(path);
if (words.containsKey(w))
results.add(path);
}
}
}
/* Waiting policies */
/**
* The search operation throws an <code>org.eclipse.core.runtime.OperationCanceledException</code>
* if the underlying indexer has not finished indexing the workspace.
*/
public static int CANCEL_IF_NOT_READY_TO_SEARCH = 0;
/**
* The search operation waits for the underlying indexer to finish indexing
* the workspace before starting the search.
*/
public static int WAIT_UNTIL_READY_TO_SEARCH = 1;
private static SearchEngine fgSearchEngine;
private HashMap fIndexes= new HashMap();
private SearchEngine() {
}
/**
*
* @return
*/
public static SearchEngine getSearchEngine() {
if (fgSearchEngine == null)
fgSearchEngine= new SearchEngine();
return fgSearchEngine;
}
/**
* Trigger removal of a resource to an index
* Note: the actual operation is performed in background
*/
public void remove(String resourceName, IPath indexedContainer) {
IIndex index= getIndex(indexedContainer, false);
if (index != null)
index.remove(resourceName);
}
public void add(IPath indexedContainer, IIndexer indexer) {
IIndex index= getIndex(indexedContainer, true);
try {
indexer.index(index);
} catch (IOException e) {
}
}
/**
* Returns the files that correspond to the paths that have been collected.
* TODO_SEARCH
*/
private IFile[] getFiles(HashSet pc, IWorkspace workspace) {
IFile[] result= new IFile[pc.size()];
int i = 0;
for (Iterator iter= pc.iterator(); iter.hasNext();) {
String resourcePath= (String)iter.next();
IPath path= new Path(resourcePath);
result[i++]= workspace.getRoot().getFile(path);
}
return result;
}
/**
* Perform the given query against the index and return results via the resultCollector.
*/
public void search(IIndexQuery search, ISearchResultCollector resultCollector,
IProgressMonitor progressMonitor, int waitingPolicy) {
HashSet pathCollector= new HashSet();
IProgressMonitor pm= progressMonitor == null ? null : new SubProgressMonitor(progressMonitor, 5);
execute(search, pathCollector, pm);
/* TODO_SEARCH */
IFile[] files= getFiles(pathCollector, ResourcesPlugin.getWorkspace());
for (int i= 0; i < files.length; i++) {
IFile file= files[i];
search.locateMatches(file, resultCollector);
}
}
public IIndex getIndex(IPath indexPath, boolean create) {
IIndex ix= (IIndex) fIndexes.get(indexPath);
if (create && ix == null) {
ix= new MyIndex();
fIndexes.put(indexPath, ix);
}
return ix;
}
private boolean execute(IIndexQuery search, HashSet pathCollector, IProgressMonitor progressMonitor) {
if (progressMonitor != null && progressMonitor.isCanceled())
throw new OperationCanceledException();
boolean isComplete= true;
IIndex[] searchIndexes= getIndexes(search);
try {
int max= searchIndexes.length;
if (progressMonitor != null) {
progressMonitor.beginTask("", max); //$NON-NLS-1$
}
for (int i = 0; i < max; i++) {
isComplete &= search(search, searchIndexes[i], pathCollector, progressMonitor);
if (progressMonitor != null) {
if (progressMonitor.isCanceled()) {
throw new OperationCanceledException();
} else {
progressMonitor.worked(1);
}
}
}
return isComplete;
} finally {
if (progressMonitor != null) {
progressMonitor.done();
}
}
}
private IIndex[] getIndexes(IIndexQuery search) {
IPath[] fIndexKeys= null; // cache of the keys for looking index up
if (fIndexKeys == null) {
ArrayList requiredIndexKeys= new ArrayList();
search.computePathsKeyingIndexFiles(requiredIndexKeys);
fIndexKeys= new IPath[requiredIndexKeys.size()];
requiredIndexKeys.toArray(fIndexKeys);
}
// acquire the in-memory indexes on the fly
int length = fIndexKeys.length;
IIndex[] indexes = new IIndex[length];
int count = 0;
for (int i = 0; i < length; i++){
// may trigger some index recreation work
IIndex index = getIndex(fIndexKeys[i], false);
if (index != null) indexes[count++] = index; // only consider indexes which are ready yet
}
if (count != length) {
System.arraycopy(indexes, 0, indexes= new IIndex[count], 0, count);
}
return indexes;
}
private boolean search(IIndexQuery search, IIndex index, HashSet pathCollector, IProgressMonitor progressMonitor) {
if (progressMonitor != null && progressMonitor.isCanceled())
throw new OperationCanceledException();
if (index == null)
return true;
try {
search.findIndexMatches(index, pathCollector, progressMonitor);
return true;
} catch (IOException e) {
return false;
}
}
}