From 3fd3ba388766504112b893d40122ee66bb83a795 Mon Sep 17 00:00:00 2001 From: Christian W. Damus Date: Thu, 5 Sep 2013 10:42:18 -0400 Subject: 415371: [CDO] Fixes in the composite search query https://bugs.eclipse.org/bugs/show_bug.cgi?id=415371 Implemented a proper composite search result to support propagation of addition/removal of search results from the component queries. This supports the expiration of search results when a CDO repository connection is closed. --- .../uml/search/ui/query/CompositePapyrusQuery.java | 91 ++++++++++++++++++++-- 1 file changed, 85 insertions(+), 6 deletions(-) (limited to 'plugins/uml/org.eclipse.papyrus.uml.search.ui/src/org') diff --git a/plugins/uml/org.eclipse.papyrus.uml.search.ui/src/org/eclipse/papyrus/uml/search/ui/query/CompositePapyrusQuery.java b/plugins/uml/org.eclipse.papyrus.uml.search.ui/src/org/eclipse/papyrus/uml/search/ui/query/CompositePapyrusQuery.java index 64e6b3a4e28..a89feebb29f 100644 --- a/plugins/uml/org.eclipse.papyrus.uml.search.ui/src/org/eclipse/papyrus/uml/search/ui/query/CompositePapyrusQuery.java +++ b/plugins/uml/org.eclipse.papyrus.uml.search.ui/src/org/eclipse/papyrus/uml/search/ui/query/CompositePapyrusQuery.java @@ -11,6 +11,8 @@ *****************************************************************************/ package org.eclipse.papyrus.uml.search.ui.query; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.eclipse.core.runtime.IProgressMonitor; @@ -22,10 +24,17 @@ import org.eclipse.core.runtime.SubMonitor; import org.eclipse.papyrus.uml.search.ui.Activator; import org.eclipse.papyrus.uml.search.ui.results.PapyrusSearchResult; import org.eclipse.search.ui.ISearchResult; +import org.eclipse.search.ui.ISearchResultListener; +import org.eclipse.search.ui.SearchResultEvent; import org.eclipse.search.ui.text.AbstractTextSearchResult; +import org.eclipse.search.ui.text.Match; +import org.eclipse.search.ui.text.MatchEvent; +import org.eclipse.search.ui.text.RemoveAllEvent; +import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; +import com.google.common.collect.Multimap; /** * A composite query delegates execution to multiple nested queries and synthesizes their results. @@ -34,6 +43,8 @@ public class CompositePapyrusQuery extends AbstractPapyrusQuery { private final List queries; + private final CompositeSearchResult searchResult = new CompositeSearchResult(); + protected CompositePapyrusQuery(List queries) { this.queries = queries; } @@ -95,29 +106,97 @@ public class CompositePapyrusQuery extends AbstractPapyrusQuery { public IStatus run(IProgressMonitor monitor) throws OperationCanceledException { List result = new java.util.ArrayList(queries.size()); + searchResult.clear(); + SubMonitor sub = SubMonitor.convert(monitor, result.size()); for(AbstractPapyrusQuery next : queries) { IStatus status = next.run(sub.newChild(1)); if(!status.isOK()) { result.add(status); } + + searchResult.addSearchResult((AbstractTextSearchResult)next.getSearchResult()); } return result.isEmpty() ? Status.OK_STATUS : (result.size() == 1) ? result.get(0) : new MultiStatus(Activator.PLUGIN_ID, 0, result.toArray(new IStatus[result.size()]), "Problems occurred in search.", null); } public ISearchResult getSearchResult() { - PapyrusSearchResult result = new PapyrusSearchResult(this); + return searchResult; + } - for(AbstractPapyrusQuery next : queries) { - AbstractTextSearchResult nextResult = (AbstractTextSearchResult)next.getSearchResult(); + // + // Nested types + // + + private final class CompositeSearchResult extends PapyrusSearchResult implements ISearchResultListener { + + private final Multimap searchResults = ArrayListMultimap.create(); - Object[] elements = nextResult.getElements(); + CompositeSearchResult() { + super(CompositePapyrusQuery.this); + } + + void clear() { + for(AbstractTextSearchResult next : searchResults.keySet()) { + next.removeListener(this); + } + searchResults.clear(); + } + + void addSearchResult(AbstractTextSearchResult searchResult) { + Object[] elements = searchResult.getElements(); for(int i = 0; i < elements.length; i++) { - result.addMatches(nextResult.getMatches(elements[i])); + Match[] matches = searchResult.getMatches(elements[i]); + searchResults.putAll(searchResult, Arrays.asList(matches)); + addMatches(matches); // I need them, too + } + + if(!searchResults.containsKey(searchResult)) { + // we have to make sure that we remember this empty result! + searchResults.putAll(searchResult, Collections. emptyList()); } + + searchResult.addListener(this); } - return result; + public void searchResultChanged(SearchResultEvent e) { + AbstractTextSearchResult source = (AbstractTextSearchResult)e.getSearchResult(); + + if(e instanceof RemoveAllEvent) { + removeAll(source); + } else if(e instanceof MatchEvent) { + MatchEvent event = (MatchEvent)e; + switch(event.getKind()) { + case MatchEvent.ADDED: + add(source, event.getMatches()); + break; + case MatchEvent.REMOVED: + remove(source, event.getMatches()); + break; + default: + Activator.log.warn("Unrecognized MatcheEvent kind: " + event.getKind()); //$NON-NLS-1$ + break; + } + } + } + + private void removeAll(AbstractTextSearchResult searchResult) { + Match[] removed = Iterables.toArray(searchResults.get(searchResult), Match.class); + + // we still need the search result in the keys! + searchResults.get(searchResult).clear(); + + removeMatches(removed); + } + + private void remove(AbstractTextSearchResult searchResult, Match[] matches) { + searchResults.get(searchResult).removeAll(Arrays.asList(matches)); + removeMatches(matches); + } + + private void add(AbstractTextSearchResult searchResult, Match[] matches) { + searchResults.putAll(searchResult, Arrays.asList(matches)); + } } } -- cgit v1.2.3