1 11 package org.eclipse.search2.internal.ui.text; 12 13 import java.util.HashMap ; 14 import java.util.HashSet ; 15 import java.util.Iterator ; 16 import java.util.Map ; 17 import java.util.Set ; 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 fMatchesToPositions= new HashMap (); 51 private Map fMatchesToSearchResults= new HashMap (); 52 private Map fFileBuffersToMatches= new HashMap (); 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 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 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 matchSet= new HashSet (fMatchesToPositions.keySet()); 108 for (Iterator 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 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 matches= (Set ) fFileBuffersToMatches.get(fb); 168 if (matches == null) { 169 matches= new HashSet (); 170 fFileBuffersToMatches.put(fb, matches); 171 } 172 matches.add(match); 173 } 174 175 private void removeFileBufferMapping(ITextFileBuffer fb, Match match) { 176 Set matches= (Set ) 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 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 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 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 matches= (Set ) fFileBuffersToMatches.get(buffer); 266 if (matches != null) { 267 Set matchSet= new HashSet (matches); 268 for (Iterator matchIterator= matchSet.iterator(); matchIterator.hasNext();) { 269 Match element= (Match) matchIterator.next(); 270 operation.run((ITextFileBuffer) buffer, element); 271 } 272 } 273 } 274 275 276 279 public void bufferDisposed(IFileBuffer buffer) { 280 final int[] trackCount= new int[1]; 281 doForExistingMatchesIn(buffer, new IFileBufferMatchOperation() { 282 285 public void run(ITextFileBuffer textBuffer, Match match) { 286 trackCount[0]++; 287 untrackPosition(textBuffer, match); 288 } 289 }); 290 } 291 292 295 public void bufferContentAboutToBeReplaced(IFileBuffer buffer) { 296 } 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 314 public void stateChanging(IFileBuffer buffer) { 315 } 317 318 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 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 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 359 public void stateValidationChanged(IFileBuffer buffer, boolean isStateValidated) { 360 } 362 363 366 public void underlyingFileMoved(IFileBuffer buffer, IPath path) { 367 } 369 370 373 public void underlyingFileDeleted(IFileBuffer buffer) { 374 } 376 377 380 public void stateChangeFailed(IFileBuffer buffer) { 381 } 383 384 387 public void queryStarting(ISearchQuery query) { 388 } 390 391 394 public void queryFinished(ISearchQuery query) { 395 } 397 398 } 399 | Popular Tags |