/*******************************************************************************
* Copyright (c) 2009 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
* Zend Technologies
*******************************************************************************/
package org.eclipse.php.internal.ui.search.text;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.search.core.text.TextSearchMatchAccess;
import org.eclipse.search.core.text.TextSearchRequestor;
import org.eclipse.search.internal.ui.text.FileMatch;
import org.eclipse.search.internal.ui.text.LineElement;
import org.eclipse.search.ui.text.Match;
/**
* Description: This is a visitor on the text results
*
* @author Roy, 2007
*/
public class ResultVisitor extends TextSearchRequestor {
private final List<Match> fResult = new LinkedList<>();
private final boolean fIsFileSearchOnly;
private final boolean fSearchInBinaries;
private final List<Match> fCachedMatches = new ArrayList<>();
public ResultVisitor(boolean isFileSearchOnly, boolean searchInBinaries) {
fIsFileSearchOnly = isFileSearchOnly;
fSearchInBinaries = searchInBinaries;
}
public ResultVisitor() {
this(false, false);
}
@Override
public boolean acceptFile(IFile file) throws CoreException {
if (fIsFileSearchOnly) {
fResult.add(new FileMatch(file));
}
flushMatches();
return true;
}
@Override
public boolean reportBinaryFile(IFile file) {
return fSearchInBinaries;
}
@Override
public boolean acceptPatternMatch(TextSearchMatchAccess matchRequestor) throws CoreException {
fCachedMatches.add(new FileMatch(matchRequestor.getFile(), matchRequestor.getMatchOffset(),
matchRequestor.getMatchLength(), getLineElement(matchRequestor.getMatchOffset(), matchRequestor)));
return true;
}
@Override
public void beginReporting() {
fCachedMatches.clear();
}
@Override
public void endReporting() {
flushMatches();
}
/**
* @return a list of {@link FileMatch}
*/
public List getResult() {
return fResult;
}
/**
* Clears resuls
*/
public void clear() {
fResult.clear();
}
private void flushMatches() {
if (!fCachedMatches.isEmpty()) {
fResult.addAll(fCachedMatches);
}
}
// @see org.eclipse.search.internal.ui.text.FileSearchQuery
// added due to changes in eclipse 3.4 API with the addition of LineElement
private LineElement getLineElement(int offset, TextSearchMatchAccess matchRequestor) {
int lineNumber = 1;
int lineStart = 0;
if (!fCachedMatches.isEmpty()) {
// match on same line as last?
FileMatch last = (FileMatch) fCachedMatches.get(fCachedMatches.size() - 1);
LineElement lineElement = last.getLineElement();
if (lineElement.contains(offset)) {
return lineElement;
}
// start with the offset and line information from the last match
lineStart = lineElement.getOffset() + lineElement.getLength();
lineNumber = lineElement.getLine() + 1;
}
if (offset < lineStart) {
return null; // offset before the last line
}
int i = lineStart;
int contentLength = matchRequestor.getFileContentLength();
while (i < contentLength) {
char ch = matchRequestor.getFileContentChar(i++);
if (ch == '\n' || ch == '\r') {
if (ch == '\r' && i < contentLength && matchRequestor.getFileContentChar(i) == '\n') {
i++;
}
if (offset < i) {
String lineContent = getContents(matchRequestor, lineStart, i); // include
// line
// delimiter
return new LineElement(matchRequestor.getFile(), lineNumber, lineStart, lineContent);
}
lineNumber++;
lineStart = i;
}
}
if (offset < i) {
String lineContent = getContents(matchRequestor, lineStart, i); // until
// end
// of
// file
return new LineElement(matchRequestor.getFile(), lineNumber, lineStart, lineContent);
}
return null; // offset outside of range
}
// @see org.eclipse.search.internal.ui.text.FileSearchQuery
// added due to changes in eclipse 3.4 API with the addition of LineElement
private static String getContents(TextSearchMatchAccess matchRequestor, int start, int end) {
StringBuilder buf = new StringBuilder();
for (int i = start; i < end; i++) {
char ch = matchRequestor.getFileContentChar(i);
if (Character.isWhitespace(ch) || Character.isISOControl(ch)) {
buf.append(' ');
} else {
buf.append(ch);
}
}
return buf.toString();
}
}