Skip to main content
summaryrefslogblamecommitdiffstats
blob: dbe0c593b9f86775de2b868c46de8b705826b4c9 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                                                                                




                                                                       
   


                                                                                 
                                   
 





                           
                     
                                        


                                                   
                                  

   
                                                                                   

                                                                                     


                                                           
                                               

   
                                                                            



                                                                              

                                                                                          
                                                                                      
   

                                                      
                                                                                     



                                                                        
   




                                                                         

           
                           

                      




                                                  
 




                                                                                
                                                         
           
                                                   



                                                     
        





                                                                                    
        
           
                                                                              
                                    
              
                                             
               


                                         
                                           






                                                                                  
        


                                                                                        
              
                                             
               
                                             
           


                                                 

                                                                  







                                                                                        
                                                                             



                                               








                                                                             











                                                                                
        

                                                       
                                             
           
                                 







                                                     
        


                                                                              
                                             
           
                                            



                                                   
                                                      



                                                                                    
        


                                                                                
                                             


                                                

                                                    

                                                                  










                                                                                       















                                                                                
        







                                                             






                                                                                










































                                                                                                              
                                                              





                                                                     







                                                            

                
 
 
/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.search.ui.text;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.search.ui.ISearchResult;
import org.eclipse.search.ui.ISearchResultListener;
import org.eclipse.search.ui.SearchResultEvent;
import org.eclipse.ui.IEditorPart;

/**
 * An abstract base implementation for text-match based search results. This search
 * result implementation consists of a list of matches. No assumptions are made about
 * the kind of elements these matches are reported against. 
 * 
 * TODO This see tag is embedded in the middle of the text.
 * 
 * see {@link org.eclipse.search.ui.text.Match}
 * 
 * 
 * This class has abstract methods to map matches to both editors and files.
 * 
 * TODO the client has to implement these methods since they are abstract. So 
 * we should give him some hints what a good implementation is.
 * 
 * If a client implements the methods related to editors, matches will be highlighted
 * automatically in participating editors. Editors must implement or adapt to ITextEditor,
 * or they must adapt to IAnnotationModel in order for match highlighting to work.<br>
 * 
 * see {@link #findContainedMatches(IEditorPart)}<br>
 * see {@link #isShownInEditor(Match,IEditorPart)}<br>
 * If a client implements the methods related to files, matches will be automatically
 * updated if the file is changed via the filebuffer infrastructure.<br>
 * see {@link org.eclipse.core.filebuffers.FileBuffers}<br>
 * see {@link #findContainedMatches(IFile)<br>
 * see {@link #getFile(Object)<br>
 */
public abstract class AbstractTextSearchResult implements ISearchResult {
	private Map fElementsToMatches;
	private List fListeners;
	private static final Match[] EMPTY_ARRAY= new Match[0];
	private MatchEvent fMatchEvent;

	/**
	 * TODO doc missing
	 * Constructor
	 */
	protected AbstractTextSearchResult() {
		fElementsToMatches= new HashMap();
		fListeners= new ArrayList();
		fMatchEvent= new MatchEvent(this);
	}

	/**
	 * Returns an array with all matches reported against the given element.
	 * 
	 * @see Match#getElement()
	 * @param element The element to report matches for.
	 * @return All matches reported for this element.
	 */
	public Match[] getMatches(Object element) {
		synchronized (fElementsToMatches) {
			return doGetMatches(element);
		}
	}
	
	private Match[] doGetMatches(Object element) {
		List matches= (List) fElementsToMatches.get(element);
		if (matches != null)
			return (Match[]) matches.toArray(new Match[matches.size()]);
		return EMPTY_ARRAY;
	}
	
	/**
	 * Adds a Match to this search result. This method does nothing if the
	 * Match is already present.
	 * <p>
	 * Subclasses may extend this method.
	 * </p>
	 * 
	 * @param match The match to add.
	 */
	public void addMatch(Match match) {
		boolean hasAdded= false;
		synchronized (fElementsToMatches) {
			hasAdded= doAddMatch(match);
		}
		if (hasAdded)
			fireChange(getSearchResultEvent(match, MatchEvent.ADDED));
	}
	
	/**
	 * Adds a number of Matches to this search result. This method does nothing for 
	 * matches that are already present.
	 * <p>
	 * Subclasses may extend this method.
	 * </p>
	 * @param matches the matches to add.
	 */
	public void addMatches(Match[] matches) {

		Set reallyAdded= new HashSet();
		synchronized (fElementsToMatches) {
			for (int i = 0; i < matches.length; i++) {
				if (doAddMatch(matches[i]))
					reallyAdded.add(matches[i]);
			}
		}
		if (reallyAdded.size() > 0)
			fireChange(getSearchResultEvent(reallyAdded, MatchEvent.ADDED));
	}
	
	private MatchEvent getSearchResultEvent(Match match, int eventKind) {
		fMatchEvent.setKind(eventKind);
		fMatchEvent.setMatch(match);
		return fMatchEvent;
	}

	private MatchEvent getSearchResultEvent(Set matches, int eventKind) {
		fMatchEvent.setKind(eventKind);
		Match[] matchArray= new Match[matches.size()];
		matches.toArray(matchArray);
		fMatchEvent.setMatches(matchArray);
		return fMatchEvent;
	}

	private boolean doAddMatch(Match match) {
		List matches= (List) fElementsToMatches.get(match.getElement());
		if (matches == null) {
			matches= new ArrayList();
			fElementsToMatches.put(match.getElement(), matches);
		}
		if (!matches.contains(match)) {
			matches.add(match);
			return true;
		}
		return false;
	}
	
	/**
	 * Removes all matches from this search result.
	 * Subclasses may extend this method.
	 */
	public void removeAll() {
		synchronized (fElementsToMatches) {
			doRemoveAll();
		}
		fireChange(new RemoveAllEvent(this));
	}
	private void doRemoveAll() {
		fElementsToMatches.clear();
	}
	
	/**
	 * Removes the given match from this search result. This method has no
	 * effect if the match is not found.
	 * Subclasses may extend this method.
	 * 
	 * @param match the match to remove.
	 */
	public void removeMatch(Match match) {
		boolean existed= false;
		synchronized (fElementsToMatches) {
			existed= doRemoveMatch(match);
		}
		if (existed)
			fireChange(getSearchResultEvent(match, MatchEvent.REMOVED));
	}
	
	/**
	 * Removes the given matches from this search result. This method has no
	 * effect for matches that are not found
	 * Subclasses may extend this method.
	 * 
	 * @param matches the matches to remove.
	 */
	public void removeMatches(Match[] matches) {
		Set existing= new HashSet();
		synchronized (fElementsToMatches) {
			for (int i = 0; i < matches.length; i++) {
				if (doRemoveMatch(matches[i]))
					existing.add(matches[i]);
			}
		}
		if (existing.size() > 0)
			fireChange(getSearchResultEvent(existing, MatchEvent.REMOVED));
	}

	
	private boolean doRemoveMatch(Match match) {
		boolean existed= false;
		List matches= (List) fElementsToMatches.get(match.getElement());
		if (matches != null) {
			existed= matches.remove(match);
			if (matches.isEmpty())
				fElementsToMatches.remove(match.getElement());
		}
		return existed;
	}
	/**
	 * {@inheritDoc}
	 */
	public void addListener(ISearchResultListener l) {
		synchronized (fListeners) {
			fListeners.add(l);
		}
	}
	
	/**
	 * {@inheritDoc}
	 */
	public void removeListener(ISearchResultListener l) {
		synchronized (fListeners) {
			fListeners.remove(l);
		}
	}
	
	/**
	 * Send the given <code>SearchResultEvent<code> to all registered search
	 * result listeners
	 * @see ISearchResultListener
	 * @param e The event to be sent.
	 */
	protected void fireChange(SearchResultEvent e) {
		HashSet copiedListeners= new HashSet();
		synchronized (fListeners) {
			copiedListeners.addAll(fListeners);
		}
		Iterator listeners= copiedListeners.iterator();
		while (listeners.hasNext()) {
			((ISearchResultListener) listeners.next()).searchResultChanged(e);
		}
	}
	/**
	 * Returns the total number of matches contained in this search result.
	 * 
	 * @return Total number of matches.
	 */
	public int getMatchCount() {
		int count= 0;
		synchronized (fElementsToMatches) {
			for (Iterator elements= fElementsToMatches.values().iterator(); elements.hasNext();) {
				List element= (List) elements.next();
				if (element != null)
					count+= element.size();
			}
		}
		return count;
	}
	/**
	 * Returns the number of matches reported against a given element. This is
	 * equivalent to calling <code>getMatches(element).length</code>
	 * 
	 * @param element The element to get the match count for.
	 * @return The number of matches reported against the element.
	 */
	public int getMatchCount(Object element) {
		List matches= (List) fElementsToMatches.get(element);
		if (matches != null)
			return matches.size();
		return 0;
	}
	/**
	 * Returns an array containing the set of all elements that matches are
	 * reported against in this search result.
	 * 
	 * @return The set of elements in this search result. 
	 */
	public Object[] getElements() {
		synchronized (fElementsToMatches) {
			return fElementsToMatches.keySet().toArray();
		}
	}

	public IEditorMatchAdapter getEditorMatchAdapter() {
		return null;
	}

	public IFileMatchAdapter getFileMatchAdapter() {
		return null;
	}
	
		

}

Back to the top