/*******************************************************************************
* Copyright (c) 2000, 2008 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.jdt.core.search;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.internal.core.JavaModel;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
/**
* A search participant describes a particular extension to a generic search mechanism, permitting
* combined search actions which will involve all required participants.
* <p>
* A search participant is involved in the indexing phase and in the search phase. The indexing
* phase consists in taking one or more search documents, parse them, and add index entries in an
* index chosen by the participant. An index is identified by a path on disk. The search phase
* consists in selecting the indexes corresponding to a search pattern and a search scope, from
* these indexes the search infrastructure extracts the document paths that match the search pattern
* asking the search participant for the corresponding document, finally the search participant is
* asked to locate the matches precisely in these search documents.
* </p>
* <p>
* This class is intended to be subclassed by clients. During the indexing phase, a subclass will be
* called with the following requests in order:
* <ul>
* <li>{@link #scheduleDocumentIndexing(SearchDocument, IPath)}</li>
* <li>{@link #indexDocument(SearchDocument, IPath)}</li>
* </ul>
* During the search phase, a subclass will be called with the following requests in order:
* <ul>
* <li>{@link #selectIndexes(SearchPattern, IJavaSearchScope)}</li>
* <li>one or more {@link #getDocument(String)}</li>
* <li>
* {@link #locateMatches(SearchDocument[], SearchPattern, IJavaSearchScope, SearchRequestor, IProgressMonitor)}
* </li>
* </ul>
* </p>
*
* @since 3.0
*/
public abstract class SearchParticipant {
/**
* Creates a new search participant.
*/
protected SearchParticipant() {
// do nothing
}
/**
* Notification that this participant's help is needed in a search.
* <p>
* This method should be re-implemented in subclasses that need to do something when the
* participant is needed in a search.
* </p>
*/
public void beginSearching() {
// do nothing
}
/**
* Notification that this participant's help is no longer needed.
* <p>
* This method should be re-implemented in subclasses that need to do something when the
* participant is no longer needed in a search.
* </p>
*/
public void doneSearching() {
// do nothing
}
/**
* Returns a displayable name of this search participant.
* <p>
* This method should be re-implemented in subclasses that need to display a meaningfull name.
* </p>
*
* @return the displayable name of this search participant
*/
public String getDescription() {
return "Search participant"; //$NON-NLS-1$
}
/**
* Returns a search document for the given path. The given document path is a string that
* uniquely identifies the document. Most of the time it is a workspace-relative path, but it
* can also be a file system path, or a path inside a zip file.
* <p>
* Implementors of this method can either create an instance of their own subclass of
* {@link SearchDocument} or return an existing instance of such a subclass.
* </p>
*
* @param documentPath the path of the document.
* @return a search document
*/
public abstract SearchDocument getDocument(String documentPath);
/**
* Indexes the given document in the given index. A search participant asked to index a document
* should parse it and call {@link SearchDocument#addIndexEntry(char[], char[])} as many times
* as needed to add index entries to the index. If delegating to another participant, it should
* use the original index location (and not the delegatee's one). In the particular case of
* delegating to the default search participant (see
* {@link SearchEngine#getDefaultSearchParticipant()}), the provided document's path must be a
* path ending with one of the {@link org.eclipse.jdt.core.JavaCore#getJavaLikeExtensions()
* Java-like extensions} or with '.class'.
* <p>
* The given index location must represent a path in the file system to a file that either
* already exists or is going to be created. If it exists, it must be an index file, otherwise
* its data might be overwritten.
* </p>
* <p>
* Clients are not expected to call this method.
* </p>
*
* @param document the document to index
* @param indexLocation the location in the file system to the index
*/
public abstract void indexDocument(SearchDocument document, IPath indexLocation);
/**
* Locates the matches in the given documents using the given search pattern and search scope,
* and reports them to the givenn search requestor. This method is called by the search engine
* once it has search documents matching the given pattern in the given search scope.
* <p>
* Note that a participant (e.g. a JSP participant) can pre-process the contents of the given
* documents, create its own documents whose contents are Java compilation units and delegate
* the match location to the default participant (see
* {@link SearchEngine#getDefaultSearchParticipant()}). Passing its own {@link SearchRequestor}
* this particpant can then map the match positions back to the original contents, create its
* own matches and report them to the original requestor.
* </p>
* <p>
* Implementors of this method should check the progress monitor for cancelation when it is safe
* and appropriate to do so. The cancelation request should be propagated to the caller by
* throwing <code>OperationCanceledException</code>.
* </p>
*
* @param documents the documents to locate matches in
* @param pattern the search pattern to use when locating matches
* @param scope the scope to limit the search to
* @param requestor the requestor to report matches to
* @param monitor the progress monitor to report progress to, or <code>null</code> if no
* progress should be reported
* @throws CoreException if the requestor had problem accepting one of the matches
*/
public abstract void locateMatches(SearchDocument[] documents, SearchPattern pattern, IJavaSearchScope scope, SearchRequestor requestor, IProgressMonitor monitor) throws CoreException;
/**
* Removes the index for a given path.
* <p>
* The given index location must represent a path in the file system to a file that already
* exists and must be an index file, otherwise nothing will be done.
* </p>
* <p>
* It is strongly recommended to use this method instead of deleting file directly otherwise
* cached index will not be removed.
* </p>
*
* @param indexLocation the location in the file system to the index
* @since 3.2
*/
public void removeIndex(IPath indexLocation) {
IndexManager manager= JavaModelManager.getIndexManager();
manager.removeIndexPath(indexLocation);
}
/**
* Schedules the indexing of the given document. Once the document is ready to be indexed,
* {@link #indexDocument(SearchDocument, IPath) indexDocument(document, indexPath)} will be
* called in a different thread than the caller's thread.
* <p>
* The given index location must represent a path in the file system to a file that either
* already exists or is going to be created. If it exists, it must be an index file, otherwise
* its data might be overwritten.
* </p>
* <p>
* When the index is no longer needed, clients should use {@link #removeIndex(IPath) } to discard
* it.
* </p>
*
* @param document the document to index
* @param indexLocation the location on the file system of the index
*/
public final void scheduleDocumentIndexing(SearchDocument document, IPath indexLocation) {
IPath documentPath= new Path(document.getPath());
Object file= JavaModel.getTarget(documentPath, true);
IPath containerPath= documentPath;
if (file instanceof IResource) {
containerPath= ((IResource)file).getProject().getFullPath();
} else if (file == null) {
containerPath= documentPath.removeLastSegments(documentPath.segmentCount() - 1);
}
IndexManager manager= JavaModelManager.getIndexManager();
// TODO (frederic) should not have to create index manually, should expose API that recreates index instead
manager.ensureIndexExists(indexLocation, containerPath);
manager.scheduleDocumentIndexing(document, containerPath, indexLocation, this);
}
/**
* Returns the collection of index locations to consider when performing the given search query
* in the given scope. The search engine calls this method before locating matches.
* <p>
* An index location represents a path in the file system to a file that holds index
* information.
* </p>
* <p>
* Clients are not expected to call this method.
* </p>
*
* @param query the search pattern to consider
* @param scope the given search scope
* @return the collection of index paths to consider
*/
public abstract IPath[] selectIndexes(SearchPattern query, IJavaSearchScope scope);
}