PageRenderTime 226ms CodeModel.GetById 216ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/bundles/plugins-trunk/LucenePlugin/src/gatchan/jedit/lucene/MarkerListQueryProcessor.java

#
Java | 196 lines | 153 code | 11 blank | 32 comment | 23 complexity | f495d55435fd22fc2ec4ad070ad55764 MD5 | raw file
  1/*
  2 * :tabSize=8:indentSize=8:noTabs=false:
  3 * :folding=explicit:collapseFolds=1:
  4 *
  5 * Copyright (C) 2009, 2011 Matthieu Casanova
  6 * Copyright (C) 2009, 2011 Shlomy Reinstein
  7 *
  8 * This program is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU General Public License
 10 * as published by the Free Software Foundation; either version 2
 11 * of the License, or any later version.
 12 * This program is distributed in the hope that it will be useful,
 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15 * GNU General Public License for more details.
 16 *
 17 * You should have received a copy of the GNU General Public License
 18 * along with this program; if not, write to the Free Software
 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 20 */
 21package gatchan.jedit.lucene;
 22
 23
 24import java.io.*;
 25import java.util.ArrayList;
 26import java.util.Collections;
 27import java.util.List;
 28
 29import marker.FileMarker;
 30
 31import org.apache.lucene.search.Query;
 32import org.apache.lucene.search.highlight.Highlighter;
 33import org.apache.lucene.search.highlight.QueryScorer;
 34import org.apache.lucene.search.highlight.Formatter;
 35import org.apache.lucene.analysis.TokenStream;
 36import org.gjt.sp.jedit.Buffer;
 37import org.gjt.sp.jedit.View;
 38import org.gjt.sp.jedit.jEdit;
 39import org.gjt.sp.jedit.io.VFS;
 40import org.gjt.sp.jedit.io.VFSFile;
 41import org.gjt.sp.jedit.io.VFSManager;
 42import org.gjt.sp.jedit.syntax.DefaultTokenHandler;
 43import org.gjt.sp.jedit.syntax.Token;
 44import org.gjt.sp.util.IOUtilities;
 45import org.gjt.sp.util.IntegerArray;
 46import org.gjt.sp.util.Log;
 47
 48/*
 49 * A query result processor that collects the lines containing results,
 50 * using the highlighter to find matches within the files.
 51 */
 52public class MarkerListQueryProcessor implements ResultProcessor
 53{
 54	private final Index index;
 55	private final List<Object> results;
 56	private final int max;
 57	private final TokenFilter tokenFilter;
 58
 59	public MarkerListQueryProcessor(Index index, List<Object> results, int max, TokenFilter tokenFilter)
 60	{
 61		this.index = index;
 62		this.results = results;
 63		this.max = max;
 64		this.tokenFilter = tokenFilter;
 65	}
 66
 67	@Override
 68	public boolean process(Query query, float score, Result result)
 69	{
 70		String s = result.getPath();
 71		addLinesMatching(query, s, max - results.size());
 72		return results.size() < max;
 73	}
 74
 75	private boolean isFiltered(int offsetInLine, String file, int line, String lineText, int lineStart)
 76	{
 77		if (! tokenFilter.isFiltering())
 78			return false;
 79		Buffer b = jEdit.openTemporary(jEdit.getActiveView(), new File(file).getParent(), file, false);
 80		b.setMode();
 81		// Mark the tokens on the line, to filter out comments and strings
 82		DefaultTokenHandler tokenHandler = new DefaultTokenHandler();
 83		b.markTokens(line, tokenHandler);
 84		Token token = tokenHandler.getTokens();
 85		int start = lineStart;
 86		int indexPos = lineStart + offsetInLine;
 87		while(token.id != Token.END)
 88		{
 89			int next = start + token.length;
 90			if (start <= indexPos && next > indexPos)
 91				break;
 92			start = next;
 93			token = token.next;
 94		}
 95		return tokenFilter.isFiltered(token);
 96	}
 97
 98	private void addLinesMatching(Query query, String file, int max)
 99	{
100		IntegerArray positions = new IntegerArray(30);
101		Formatter sf = new SearchFormatter(positions, max);
102		QueryScorer scorer = new QueryScorer(query);
103		StringBuilder sb = new StringBuilder();
104		List<Integer> lineStart = new ArrayList<Integer>(500);
105		BufferedReader br = null;
106		try
107		{
108			br = getReader(file);
109			if (br == null)
110			{
111				Log.log(Log.WARNING, this, "Cannot read file " + file +
112					" maybe it doesn't exist anymore");
113				return;
114			}
115			String s;
116			char sep = '\n';
117			while ((s = br.readLine()) != null)
118			{
119				if (sb.length() > 0)
120					sb.append(sep);
121				lineStart.add(sb.length());
122				sb.append(s);
123			}
124			Highlighter h = new Highlighter(sf, scorer);
125			h.setMaxDocCharsToAnalyze(sb.length());
126			String text = sb.toString();
127			TokenStream tokenStream = index.getAnalyzer().tokenStream("field", new StringReader(text));
128			h.getBestFragments(tokenStream, text, 0);
129		}
130		catch (Exception e)
131		{
132			Log.log(Log.ERROR, this, e);
133		}
134		finally
135		{
136			IOUtilities.closeQuietly(br);
137		}
138
139		for (int i = 0; i < positions.getSize(); i += 2)
140		{
141			int tokenStart = positions.get(i), tokenEnd = positions.get(i + 1);
142			int start = tokenStart, stop = tokenEnd;
143			// Find beginning and end of line
144			while ((start >= 0) && (sb.charAt(start) != '\n'))
145				start--;
146			start++;
147			while ((stop < sb.length()) && (sb.charAt(stop) != '\n'))
148				stop++;
149			String lineText = sb.substring(start, stop);
150			int line = Collections.binarySearch(lineStart, tokenStart);
151			if (line < 0)
152				line = -line - 2;
153			int startOffset = tokenStart - start;
154			if (isFiltered(startOffset, file, line, lineText, start))
155				continue;
156			FileMarker marker = new FileMarker(file, line, lineText);
157			int endOffset = startOffset + tokenEnd - tokenStart;
158			if (endOffset > lineText.length())
159				endOffset = lineText.length();
160			marker.addSelection(marker.new Selection(startOffset,
161				startOffset + tokenEnd - tokenStart));
162			results.add(marker);
163		}
164	}
165
166	/**
167	 * Return a reader for the given file
168	 * @param file the file
169	 * @return a reader or null of the reader cannot be opened or if
170	 * the file do not exist anymore
171	 */
172	private static BufferedReader getReader(String file)
173	{
174		VFS vfs = VFSManager.getVFSForPath(file);
175		View view = jEdit.getActiveView();
176		Object session = vfs.createVFSSession(file, view);
177		BufferedReader reader = null;
178		try
179		{
180			VFSFile vfsFile = vfs._getFile(session, file, view);
181			if (vfsFile != null)
182			{
183				InputStream inputStream = vfs._createInputStream(session,
184					vfsFile.getPath(), false, view);
185				if (inputStream != null)
186					reader = new BufferedReader(new InputStreamReader(
187						inputStream));
188			}
189		}
190		catch (IOException e)
191		{
192			Log.log(Log.ERROR, MarkerListQueryProcessor.class, e);
193		}
194		return reader;
195	}
196}