KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > search2 > internal > ui > text > PositionTracker


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.search2.internal.ui.text;
12
13 import java.util.HashMap JavaDoc;
14 import java.util.HashSet JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.Map JavaDoc;
17 import java.util.Set JavaDoc;
18
19 import org.eclipse.search.internal.ui.SearchPlugin;
20 import org.eclipse.search.ui.IQueryListener;
21 import org.eclipse.search.ui.ISearchQuery;
22 import org.eclipse.search.ui.ISearchResult;
23 import org.eclipse.search.ui.ISearchResultListener;
24 import org.eclipse.search.ui.NewSearchUI;
25 import org.eclipse.search.ui.SearchResultEvent;
26 import org.eclipse.search.ui.text.AbstractTextSearchResult;
27 import org.eclipse.search.ui.text.IFileMatchAdapter;
28 import org.eclipse.search.ui.text.Match;
29 import org.eclipse.search.ui.text.MatchEvent;
30 import org.eclipse.search.ui.text.RemoveAllEvent;
31
32 import org.eclipse.core.filebuffers.FileBuffers;
33 import org.eclipse.core.filebuffers.IFileBuffer;
34 import org.eclipse.core.filebuffers.IFileBufferListener;
35 import org.eclipse.core.filebuffers.ITextFileBuffer;
36 import org.eclipse.core.filebuffers.LocationKind;
37
38 import org.eclipse.core.resources.IFile;
39 import org.eclipse.core.runtime.IPath;
40 import org.eclipse.core.runtime.IStatus;
41 import org.eclipse.core.runtime.Status;
42
43 import org.eclipse.jface.text.BadLocationException;
44 import org.eclipse.jface.text.IDocument;
45 import org.eclipse.jface.text.Position;
46
47
48 public class PositionTracker implements IQueryListener, ISearchResultListener, IFileBufferListener {
49
50     private Map JavaDoc fMatchesToPositions= new HashMap JavaDoc();
51     private Map JavaDoc fMatchesToSearchResults= new HashMap JavaDoc();
52     private Map JavaDoc fFileBuffersToMatches= new HashMap JavaDoc();
53     
54     private interface IFileBufferMatchOperation {
55         void run(ITextFileBuffer buffer, Match match);
56     }
57     
58     public PositionTracker() {
59         NewSearchUI.addQueryListener(this);
60         FileBuffers.getTextFileBufferManager().addFileBufferListener(this);
61     }
62     
63     // tracking search results --------------------------------------------------------------
64
public void queryAdded(ISearchQuery query) {
65         if (query.getSearchResult() instanceof AbstractTextSearchResult) {
66             query.getSearchResult().addListener(this);
67         }
68     }
69     
70     public void queryRemoved(ISearchQuery query) {
71         ISearchResult result= query.getSearchResult();
72         if (result instanceof AbstractTextSearchResult) {
73             untrackAll((AbstractTextSearchResult)result);
74             result.removeListener(this);
75         }
76     }
77
78     // tracking matches ---------------------------------------------------------------------
79
public void searchResultChanged(SearchResultEvent e) {
80         if (e instanceof MatchEvent) {
81             MatchEvent evt= (MatchEvent)e;
82             Match[] matches = evt.getMatches();
83             int kind = evt.getKind();
84             AbstractTextSearchResult result = (AbstractTextSearchResult) e.getSearchResult();
85             for (int i = 0; i < matches.length; i++) {
86                 ITextFileBuffer fb= getTrackedFileBuffer(result, matches[i].getElement());
87                 if (fb != null) {
88                     updateMatch(matches[i], fb, kind, result);
89                 }
90             }
91         } else if (e instanceof RemoveAllEvent) {
92             RemoveAllEvent evt= (RemoveAllEvent)e;
93             ISearchResult result= evt.getSearchResult();
94             untrackAll((AbstractTextSearchResult)result);
95         }
96     }
97
98     private void updateMatch(Match match, ITextFileBuffer fb, int kind, AbstractTextSearchResult result) {
99         if (kind == MatchEvent.ADDED) {
100             trackPosition(result, fb, match);
101         } else if (kind == MatchEvent.REMOVED) {
102             untrackPosition(fb, match);
103         }
104     }
105
106     private void untrackAll(AbstractTextSearchResult result) {
107         Set JavaDoc matchSet= new HashSet JavaDoc(fMatchesToPositions.keySet());
108         for (Iterator JavaDoc matches= matchSet.iterator(); matches.hasNext();) {
109             Match match= (Match) matches.next();
110             AbstractTextSearchResult matchContainer= (AbstractTextSearchResult) fMatchesToSearchResults.get(match);
111             if (result.equals(matchContainer)) {
112                 ITextFileBuffer fb= getTrackedFileBuffer(result, match.getElement());
113                 if (fb != null) {
114                     untrackPosition(fb, match);
115                 }
116             }
117         }
118     }
119
120     private void untrackPosition(ITextFileBuffer fb, Match match) {
121         Position position= (Position) fMatchesToPositions.get(match);
122         if (position != null) {
123             removeFileBufferMapping(fb, match);
124             fMatchesToSearchResults.remove(match);
125             fMatchesToPositions.remove(match);
126             fb.getDocument().removePosition(position);
127         }
128     }
129
130     private void trackPosition(AbstractTextSearchResult result, ITextFileBuffer fb, Match match) {
131         int offset = match.getOffset();
132         int length = match.getLength();
133         if (offset < 0 || length < 0)
134             return;
135         
136         try {
137             IDocument doc= fb.getDocument();
138             Position position= new Position(offset, length);
139             if (match.getBaseUnit() == Match.UNIT_LINE) {
140                 position= convertToCharacterPosition(position, doc);
141             }
142             doc.addPosition(position);
143             fMatchesToSearchResults.put(match, result);
144             fMatchesToPositions.put(match, position);
145             addFileBufferMapping(fb, match);
146         } catch (BadLocationException e) {
147             // the match is outside the document
148
result.removeMatch(match);
149         }
150     }
151
152     public static Position convertToCharacterPosition(Position linePosition, IDocument doc) throws BadLocationException {
153         int lineOffset= linePosition.getOffset();
154         int lineLength= linePosition.getLength();
155         
156         int charOffset= doc.getLineOffset(lineOffset);
157         int charLength= 0;
158         if (lineLength > 0) {
159             int lastLine= lineOffset+lineLength-1;
160             int endPosition= doc.getLineOffset(lastLine)+doc.getLineLength(lastLine);
161             charLength= endPosition-charOffset;
162         }
163         return new Position(charOffset, charLength);
164     }
165
166     private void addFileBufferMapping(ITextFileBuffer fb, Match match) {
167         Set JavaDoc matches= (Set JavaDoc) fFileBuffersToMatches.get(fb);
168         if (matches == null) {
169             matches= new HashSet JavaDoc();
170             fFileBuffersToMatches.put(fb, matches);
171         }
172         matches.add(match);
173     }
174
175     private void removeFileBufferMapping(ITextFileBuffer fb, Match match) {
176         Set JavaDoc matches= (Set JavaDoc) fFileBuffersToMatches.get(fb);
177         if (matches != null) {
178             matches.remove(match);
179             if (matches.size() == 0)
180                 fFileBuffersToMatches.remove(fb);
181         }
182     }
183     
184     private ITextFileBuffer getTrackedFileBuffer(AbstractTextSearchResult result, Object JavaDoc element) {
185         IFileMatchAdapter adapter= result.getFileMatchAdapter();
186         if (adapter == null)
187             return null;
188         IFile file= adapter.getFile(element);
189         if (file == null)
190             return null;
191         if (!file.exists())
192             return null;
193         return FileBuffers.getTextFileBufferManager().getTextFileBuffer(file.getFullPath(), LocationKind.IFILE);
194     }
195     
196     public Position getCurrentPosition(Match match) {
197         Position pos= (Position)fMatchesToPositions.get(match);
198         if (pos == null)
199             return pos;
200         AbstractTextSearchResult result= (AbstractTextSearchResult) fMatchesToSearchResults.get(match);
201         if (match.getBaseUnit() == Match.UNIT_LINE && result != null) {
202             ITextFileBuffer fb= getTrackedFileBuffer(result, match.getElement());
203             if (fb != null) {
204                 IDocument doc= fb.getDocument();
205                 try {
206                     pos= convertToLinePosition(pos, doc);
207                 } catch (BadLocationException e) {
208                     
209                 }
210             }
211         }
212         
213         return pos;
214     }
215     
216     public static Position convertToLinePosition(Position pos, IDocument doc) throws BadLocationException {
217         int offset= doc.getLineOfOffset(pos.getOffset());
218         int end= doc.getLineOfOffset(pos.getOffset()+pos.getLength());
219         int lineLength= end-offset;
220         if (pos.getLength() > 0 && lineLength == 0) {
221             // if the character length is > 0, add the last line, too
222
lineLength++;
223         }
224         return new Position(offset, lineLength);
225     }
226
227     public void dispose() {
228         NewSearchUI.removeQueryListener(this);
229         FileBuffers.getTextFileBufferManager().removeFileBufferListener(this);
230     }
231
232     // IFileBufferListener implementation ---------------------------------------------------------------------
233
/* (non-Javadoc)
234      * @see org.eclipse.core.filebuffers.IFileBufferListener#bufferCreated(org.eclipse.core.filebuffers.IFileBuffer)
235      */

236     public void bufferCreated(IFileBuffer buffer) {
237         final int[] trackCount= new int[1];
238         if (!(buffer instanceof ITextFileBuffer))
239             return;
240         
241         IFile file= FileBuffers.getWorkspaceFileAtLocation(buffer.getLocation());
242         if (file == null)
243             return;
244
245         ISearchQuery[] queries= NewSearchUI.getQueries();
246         for (int i = 0; i < queries.length; i++) {
247             ISearchResult result = queries[i].getSearchResult();
248             if (result instanceof AbstractTextSearchResult) {
249                 AbstractTextSearchResult textResult = (AbstractTextSearchResult) result;
250                 IFileMatchAdapter adapter = textResult.getFileMatchAdapter();
251                 if (adapter != null) {
252                     Match[] matches = adapter.computeContainedMatches(textResult, file);
253                     for (int j = 0; j < matches.length; j++) {
254                         trackCount[0]++;
255                         trackPosition((AbstractTextSearchResult) result, (ITextFileBuffer) buffer, matches[j]);
256                     }
257                 }
258             }
259         }
260     }
261         
262     private void doForExistingMatchesIn(IFileBuffer buffer, IFileBufferMatchOperation operation) {
263         if (!(buffer instanceof ITextFileBuffer))
264             return;
265         Set JavaDoc matches= (Set JavaDoc) fFileBuffersToMatches.get(buffer);
266         if (matches != null) {
267             Set JavaDoc matchSet= new HashSet JavaDoc(matches);
268             for (Iterator JavaDoc matchIterator= matchSet.iterator(); matchIterator.hasNext();) {
269                 Match element= (Match) matchIterator.next();
270                 operation.run((ITextFileBuffer) buffer, element);
271             }
272         }
273     }
274     
275
276     /* (non-Javadoc)
277      * @see org.eclipse.core.filebuffers.IFileBufferListener#bufferDisposed(org.eclipse.core.filebuffers.IFileBuffer)
278      */

279     public void bufferDisposed(IFileBuffer buffer) {
280         final int[] trackCount= new int[1];
281         doForExistingMatchesIn(buffer, new IFileBufferMatchOperation() {
282             /* (non-Javadoc)
283              * @see org.eclipse.search.internal.model.PositionTracker.FileBufferMatchRunnable#run(org.eclipse.core.filebuffers.ITextFileBuffer, org.eclipse.search.ui.model.text.Match)
284              */

285             public void run(ITextFileBuffer textBuffer, Match match) {
286                 trackCount[0]++;
287                 untrackPosition(textBuffer, match);
288             }
289         });
290     }
291
292     /* (non-Javadoc)
293      * @see org.eclipse.core.filebuffers.IFileBufferListener#bufferContentAboutToBeReplaced(org.eclipse.core.filebuffers.IFileBuffer)
294      */

295     public void bufferContentAboutToBeReplaced(IFileBuffer buffer) {
296         // not interesting for us.
297
}
298
299     public void bufferContentReplaced(IFileBuffer buffer) {
300         final int[] trackCount= new int[1];
301         doForExistingMatchesIn(buffer, new IFileBufferMatchOperation() {
302             public void run(ITextFileBuffer textBuffer, Match match) {
303                 trackCount[0]++;
304                 AbstractTextSearchResult result= (AbstractTextSearchResult) fMatchesToSearchResults.get(match);
305                 untrackPosition(textBuffer, match);
306                 trackPosition(result, textBuffer, match);
307             }
308         });
309     }
310
311     /* (non-Javadoc)
312      * @see org.eclipse.core.filebuffers.IFileBufferListener#stateChanging(org.eclipse.core.filebuffers.IFileBuffer)
313      */

314     public void stateChanging(IFileBuffer buffer) {
315         // not interesting for us
316
}
317
318     /* (non-Javadoc)
319      * @see org.eclipse.core.filebuffers.IFileBufferListener#dirtyStateChanged(org.eclipse.core.filebuffers.IFileBuffer, boolean)
320      */

321     public void dirtyStateChanged(IFileBuffer buffer, boolean isDirty) {
322         if (isDirty)
323             return;
324         final int[] trackCount= new int[1];
325         doForExistingMatchesIn(buffer, new IFileBufferMatchOperation() {
326             /* (non-Javadoc)
327              * @see org.eclipse.search.internal.model.PositionTracker.FileBufferMatchRunnable#run(org.eclipse.core.filebuffers.ITextFileBuffer, org.eclipse.search.ui.model.text.Match)
328              */

329             public void run(ITextFileBuffer textBuffer, Match match) {
330                 trackCount[0]++;
331                 Position pos= (Position) fMatchesToPositions.get(match);
332                 if (pos != null) {
333                     if (pos.isDeleted()) {
334                         AbstractTextSearchResult result= (AbstractTextSearchResult) fMatchesToSearchResults.get(match);
335                         // might be that the containing element has been removed.
336
if (result != null) {
337                             result.removeMatch(match);
338                         }
339                         untrackPosition(textBuffer, match);
340                     } else {
341                         if (match.getBaseUnit() == Match.UNIT_LINE) {
342                             try {
343                                 pos= convertToLinePosition(pos, textBuffer.getDocument());
344                             } catch (BadLocationException e) {
345                                 SearchPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, SearchPlugin.getID(), 0, e.getLocalizedMessage(), e));
346                             }
347                         }
348                         match.setOffset(pos.getOffset());
349                         match.setLength(pos.getLength());
350                     }
351                 }
352             }
353         });
354     }
355
356     /* (non-Javadoc)
357      * @see org.eclipse.core.filebuffers.IFileBufferListener#stateValidationChanged(org.eclipse.core.filebuffers.IFileBuffer, boolean)
358      */

359     public void stateValidationChanged(IFileBuffer buffer, boolean isStateValidated) {
360         // not interesting for us.
361
}
362
363     /* (non-Javadoc)
364      * @see org.eclipse.core.filebuffers.IFileBufferListener#underlyingFileMoved(org.eclipse.core.filebuffers.IFileBuffer, org.eclipse.core.runtime.IPath)
365      */

366     public void underlyingFileMoved(IFileBuffer buffer, IPath path) {
367         // not interesting for us.
368
}
369
370     /* (non-Javadoc)
371      * @see org.eclipse.core.filebuffers.IFileBufferListener#underlyingFileDeleted(org.eclipse.core.filebuffers.IFileBuffer)
372      */

373     public void underlyingFileDeleted(IFileBuffer buffer) {
374         // not interesting for us.
375
}
376
377     /* (non-Javadoc)
378      * @see org.eclipse.core.filebuffers.IFileBufferListener#stateChangeFailed(org.eclipse.core.filebuffers.IFileBuffer)
379      */

380     public void stateChangeFailed(IFileBuffer buffer) {
381         // not interesting for us.
382
}
383
384     /* (non-Javadoc)
385      * @see org.eclipse.search.ui.IQueryListener#queryStarting(org.eclipse.search.ui.ISearchQuery)
386      */

387     public void queryStarting(ISearchQuery query) {
388         // not interested here
389
}
390
391     /* (non-Javadoc)
392      * @see org.eclipse.search.ui.IQueryListener#queryFinished(org.eclipse.search.ui.ISearchQuery)
393      */

394     public void queryFinished(ISearchQuery query) {
395         // not interested
396
}
397
398 }
399
Popular Tags