Skip to content

Commit 4a4172c

Browse files
howlgeriloveeclipse
authored andcommitted
Extend AbstractSearchProcessor#postSearch(...) for more information
The `org.eclipse.help.searchProcessor` extension point allows to modify the help search results. This is done by calling the `postSearch(...)` method of all implementations of `org.eclipse.help.search.AbstractSearchProcessor` specified by this extension point. In some cases, the search results to be modified and the query that are passed as parameters to the `postSearch(...)` method may not be enough. So this change adds another `postSearch(...)` method with additional parameters like the locale and the scopes if any. The simpler `postSearch(...)` is be kept for backward compatibility. Additionally, if `preSearch(...)` returns a `SearchProcessorInfo` with an empty, non-`null` query (`""`), no search will be executed, resulting in no search results or in the search results that has been added via `postSearch(...)`.
1 parent 87a5e5a commit 4a4172c

File tree

8 files changed

+342
-47
lines changed

8 files changed

+342
-47
lines changed

ua/org.eclipse.help.base/src/org/eclipse/help/internal/search/SearchResults.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.Iterator;
2020
import java.util.List;
2121

22+
import org.eclipse.help.IHelpResource;
2223
import org.eclipse.help.IToc;
2324
import org.eclipse.help.ITopic;
2425
import org.eclipse.help.base.AbstractHelpScope;
@@ -297,4 +298,9 @@ private ArrayList<CriterionResource> getCriteriaScopes(WorkingSet[] wSets){
297298
public void addQTCException(QueryTooComplexException exception) throws QueryTooComplexException {
298299
this.searchException = exception;
299300
}
301+
302+
public IHelpResource[] getScopes() {
303+
return scopes == null ? null : scopes.toArray(IHelpResource[]::new);
304+
}
305+
300306
}

ua/org.eclipse.help.base/src/org/eclipse/help/internal/search/federated/LocalHelp.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ public class LocalHelp implements ISearchEngine2 {
3737
public void run(String query, ISearchScope scope,
3838
final ISearchEngineResultCollector collector,
3939
IProgressMonitor monitor) throws CoreException {
40+
String originalQuery = query;
4041

42+
// Pre search
4143
AbstractSearchProcessor processors[] = SearchManager.getSearchProcessors();
4244
altList = new ArrayList<>();
4345
for (AbstractSearchProcessor processor : processors) {
@@ -56,28 +58,30 @@ public void run(String query, ISearchScope scope,
5658
}
5759
altList.sort(null);
5860

59-
61+
// Search
6062
SearchQuery searchQuery = new SearchQuery();
6163
searchQuery.setSearchWord(query);
6264
WorkingSet[] workingSets = null;
6365
LocalHelpScope localScope = (LocalHelpScope) scope;
6466
if (localScope.getWorkingSet() != null)
6567
workingSets = new WorkingSet[] { localScope.getWorkingSet() };
66-
SearchResults localResults = new SearchResults(workingSets, MAX_HITS,
67-
Platform.getNL());
68+
SearchResults localResults = new SearchResults(workingSets, MAX_HITS, Platform.getNL());
6869
// If the indexer has been started and is currently running,
6970
// wait for it to finish.
7071
try {
7172
Job.getJobManager().join(IndexerJob.FAMILY, monitor);
7273
} catch (InterruptedException e) {
7374
}
74-
BaseHelpSystem.getSearchManager().search(searchQuery, localResults,
75-
monitor);
75+
if (!"".equals(query)) { //$NON-NLS-1$
76+
BaseHelpSystem.getSearchManager().search(searchQuery, localResults, monitor);
77+
}
7678

79+
// Post search
7780
ISearchResult results[] = SearchManager.convertHitsToResults(localResults.getSearchHits());
7881
boolean reset = false;
7982
for (AbstractSearchProcessor processor : processors) {
80-
ISearchResult tmp[] = processor.postSearch(query, results);
83+
ISearchResult tmp[] = processor.postSearch(query, originalQuery, results, searchQuery.getLocale(),
84+
localResults.getScopes());
8185
if (tmp!=null)
8286
{
8387
reset = true;

ua/org.eclipse.help.base/src/org/eclipse/help/search/AbstractSearchProcessor.java

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
package org.eclipse.help.search;
1616

17+
import org.eclipse.help.IHelpResource;
18+
1719
/**
1820
* This class is responsible for handling any pre or post
1921
* search processing events, including query manipulation
@@ -34,20 +36,52 @@ public AbstractSearchProcessor()
3436
* See {@link SearchProcessorInfo} for types of information that can be used by
3537
* the search display.
3638
*
37-
* @return <code>SearchProcessorInfo</code>, or <code>null</code> for no changes.
39+
* If a {@link SearchProcessorInfo} with an empty, non-{@code null} query
40+
* ({@code ""}) is returned, no search will be executed, resulting in no search
41+
* results.
42+
*
43+
* @return {@link SearchProcessorInfo}, or {@code null} for no changes.
3844
*/
3945
public abstract SearchProcessorInfo preSearch(String query);
4046

4147
/**
4248
* This method is called after the search is performed.
4349
*
44-
* Results are stored as an array of ISearchResult containing
45-
* all available data.
50+
* This method can be used to return a modified result set. For example, one can
51+
* change the result score of an item, add new results to the top of the list,
52+
* or remove results.
4653
*
47-
* This method can be used to return a modified result set. For example, one can change the
48-
* result score of an item, add new results to the top of the list, or remove results.
54+
* This method exists for backwards compatibility. Overwrite
55+
* {@link #postSearch(String, String, ISearchResult[], String, IHelpResource[])}
56+
* if more information like the locale, etc. is needed instead.
4957
*
50-
* @return <code>{@link ISearchResult}[]</code>, or <code>null</code> for no changes.
58+
* @return The modified results, or {@code null} for no changes.
5159
*/
5260
public abstract ISearchResult[] postSearch(String query, ISearchResult[] results);
61+
62+
/**
63+
* This method is called after the search is performed.
64+
*
65+
* This method can be used to return a modified result set. For example, one can
66+
* change the result score of an item, add new results to the top of the list,
67+
* or remove results.
68+
*
69+
* @param query The actually query that was executed (after any changes
70+
* made by {@link #preSearch(String)}).
71+
* @param originalQuery The original query before any changes made by
72+
* {@link #preSearch(String)}.
73+
* @param results The results of the executed query.
74+
* @param results The locale.
75+
* @param results The set scopes (might be {@code null}).
76+
*
77+
* @return The modified results, or {@code null} for no changes.
78+
*
79+
* @see #postSearch(String, ISearchResult[])
80+
*
81+
* @since 4.5
82+
*/
83+
public ISearchResult[] postSearch(String query, String originalQuery, ISearchResult[] results, String locale,
84+
IHelpResource[] scopes) {
85+
return postSearch(query, results);
86+
}
5387
}

ua/org.eclipse.help.webapp/src/org/eclipse/help/internal/webapp/data/SearchData.java

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ private void readDisplayFlags(HttpServletRequest request, HttpServletResponse re
135135
}
136136

137137
public void readSearchResults() {
138+
String originalSearchWord = searchWord;
138139

139140
// try loading search results or get the indexing progress info.
140141
if (isSearchRequest() && !isScopeRequest()) {
@@ -167,7 +168,7 @@ public void readSearchResults() {
167168
}
168169
altList.sort(null);
169170

170-
loadSearchResults();
171+
SearchResults searchResults = loadSearchResults();
171172
if (queryException != null) {
172173
return;
173174
}
@@ -183,9 +184,9 @@ public void readSearchResults() {
183184
ISearchResult results[] = SearchManager.convertHitsToResults(hits);
184185
boolean reset= false;
185186
for (AbstractSearchProcessor processor : processors) {
186-
ISearchResult tmp[] = processor.postSearch(searchWord,results);
187-
if (tmp!=null)
188-
{
187+
ISearchResult tmp[] = processor.postSearch(searchWord, originalSearchWord, results, getLocale(),
188+
searchResults == null ? null : searchResults.getScopes());
189+
if (tmp != null) {
189190
reset = true;
190191
results = tmp;
191192
}
@@ -438,34 +439,36 @@ private void saveWorkingSet(String workingSet) {
438439
* Call the search engine, and get results or the percentage of indexed
439440
* documents.
440441
*/
441-
private void loadSearchResults() {
442+
private SearchResults loadSearchResults() {
442443
try {
443444
SearchProgressMonitor pm = SearchProgressMonitor
444445
.getProgressMonitor(getLocale());
445446
if (pm.isDone()) {
446447
this.indexCompletion = 100;
447448
SearchResults results = createHitCollector();
448-
BaseHelpSystem.getSearchManager().search(createSearchQuery(),
449-
results, pm);
450-
hits = results.getSearchHits();
449+
if ("".equals(searchWord)) { //$NON-NLS-1$
450+
hits = new SearchHit[0];
451+
} else {
452+
BaseHelpSystem.getSearchManager().search(createSearchQuery(), results, pm);
453+
hits = results.getSearchHits();
454+
}
451455
if (hits == null) {
452456
ILog.of(getClass()).warn("No search results returned. Help index is in use."); //$NON-NLS-1$
453457
}
454-
return;
458+
return results;
455459
}
456460
// progress
457461
indexCompletion = pm.getPercentage();
458462
if (indexCompletion >= 100) {
459463
// 38573 We do not have results, so index cannot be 100
460464
indexCompletion = 100 - 1;
461465
}
462-
return;
463466
} catch (QueryTooComplexException qe) {
464467
queryException = qe;
465468
} catch (Exception e) {
466469
this.indexCompletion = 0;
467470
}
468-
471+
return null;
469472
}
470473

471474
private ISearchQuery createSearchQuery() {

ua/org.eclipse.ua.tests/help/org/eclipse/ua/tests/help/search/AllSearchTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2006, 2012 IBM Corporation and others.
2+
* Copyright (c) 2006, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -32,6 +32,7 @@
3232
MetaKeywords.class, //
3333
SearchParticipantTest.class, //
3434
SearchParticipantXMLTest.class, //
35+
SearchProcessorTest.class, //
3536
SearchRanking.class, //
3637
WorkingSetManagerTest.class, //
3738
InfocenterWorkingSetManagerTest.class, //
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Holger Voormann and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*******************************************************************************/
11+
package org.eclipse.ua.tests.help.search;
12+
13+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
14+
import static org.junit.jupiter.api.Assertions.assertEquals;
15+
import static org.junit.jupiter.api.Assertions.assertNull;
16+
import static org.junit.jupiter.api.Assertions.fail;
17+
18+
import java.util.ArrayList;
19+
import java.util.Collections;
20+
21+
import org.eclipse.core.runtime.IStatus;
22+
import org.eclipse.core.runtime.NullProgressMonitor;
23+
import org.eclipse.help.IHelpResource;
24+
import org.eclipse.help.internal.search.SearchQuery;
25+
import org.eclipse.help.internal.search.SearchResult;
26+
import org.eclipse.help.internal.search.federated.LocalHelp;
27+
import org.eclipse.help.internal.search.federated.LocalHelpScope;
28+
import org.eclipse.help.search.AbstractSearchProcessor;
29+
import org.eclipse.help.search.ISearchEngineResult;
30+
import org.eclipse.help.search.ISearchEngineResultCollector;
31+
import org.eclipse.help.search.ISearchResult;
32+
import org.eclipse.help.search.SearchProcessorInfo;
33+
import org.junit.jupiter.api.Test;
34+
35+
public class SearchProcessorTest {
36+
37+
@Test
38+
void testPreSearch() {
39+
var processor = new AbstractSearchProcessor() {
40+
41+
@Override
42+
public SearchProcessorInfo preSearch(String query) {
43+
SearchProcessorInfo info = new SearchProcessorInfo();
44+
info.setQuery("jkijkijkk");
45+
return info;
46+
}
47+
48+
@Override
49+
public ISearchResult[] postSearch(String query, ISearchResult[] results) {
50+
return null;
51+
}
52+
53+
};
54+
test(processor, new String[] { "/org.eclipse.ua.tests/participant1.xml" });
55+
}
56+
57+
@Test
58+
void testPostSearch() {
59+
var processor = new AbstractSearchProcessor() {
60+
61+
@Override
62+
public SearchProcessorInfo preSearch(String query) {
63+
SearchProcessorInfo info = new SearchProcessorInfo();
64+
info.setQuery("jkijkijkk");
65+
return info;
66+
}
67+
68+
@Override
69+
public ISearchResult[] postSearch(String query, ISearchResult[] results) {
70+
assertEquals("jkijkijkk", query);
71+
assertEquals(1, results.length);
72+
assertEquals("/org.eclipse.ua.tests/participant1.xml", withoutQueryPart(results[0].getHref()));
73+
var addedResult = new SearchResult();
74+
addedResult.setHref("/org.eclipse.ua.tests/added");
75+
return new ISearchResult[] { addedResult };
76+
}
77+
78+
};
79+
test(processor, new String[] { "/org.eclipse.ua.tests/added" });
80+
}
81+
82+
@Test
83+
void testExtendedPostSearch() {
84+
var processor = new AbstractSearchProcessor() {
85+
86+
@Override
87+
public SearchProcessorInfo preSearch(String query) {
88+
SearchProcessorInfo info = new SearchProcessorInfo();
89+
info.setQuery("olhoykk");
90+
return info;
91+
}
92+
93+
@Override
94+
public ISearchResult[] postSearch(String query, ISearchResult[] results) {
95+
return null;
96+
}
97+
98+
@Override
99+
public ISearchResult[] postSearch(String query, String originalQuery, ISearchResult[] results,
100+
String locale, IHelpResource[] scopes) {
101+
assertEquals("olhoykk", query);
102+
assertEquals(WrappedSearchProcessor.QUERY, originalQuery);
103+
assertEquals(1, results.length);
104+
assertEquals("/org.eclipse.ua.tests/participant2.xml", withoutQueryPart(results[0].getHref()));
105+
assertEquals(new SearchQuery().getLocale(), locale);
106+
assertNull(scopes);
107+
var addedResult = new SearchResult();
108+
addedResult.setHref("/org.eclipse.ua.tests/added2");
109+
return new ISearchResult[] { addedResult };
110+
}
111+
112+
};
113+
test(processor, new String[] { "/org.eclipse.ua.tests/added2" });
114+
}
115+
116+
@Test
117+
void testNullProcessor() {
118+
var processor = new AbstractSearchProcessor() {
119+
120+
@Override
121+
public SearchProcessorInfo preSearch(String query) {
122+
assertEquals(WrappedSearchProcessor.QUERY, query);
123+
return null;
124+
}
125+
126+
@Override
127+
public ISearchResult[] postSearch(String query, ISearchResult[] results) {
128+
return null;
129+
}
130+
131+
};
132+
test(processor, new String[0]);
133+
}
134+
135+
private void test(AbstractSearchProcessor processor, String[] expected) {
136+
try (var autoClosable = WrappedSearchProcessor.set(processor)) {
137+
String[] hits = search(WrappedSearchProcessor.QUERY);
138+
assertArrayEquals(expected, hits);
139+
} catch (Exception e) {
140+
e.printStackTrace();
141+
fail(e);
142+
}
143+
}
144+
145+
private static String[] search(String query) throws Exception {
146+
147+
var foundHrefs = new ArrayList<String>();
148+
ISearchEngineResultCollector collector = new ISearchEngineResultCollector() {
149+
150+
@Override
151+
public void accept(ISearchEngineResult searchResult) {
152+
foundHrefs.add(withoutQueryPart(searchResult.getHref()));
153+
}
154+
155+
@Override
156+
public void accept(ISearchEngineResult[] searchResults) {
157+
for (ISearchEngineResult searchResult : searchResults) {
158+
foundHrefs.add(withoutQueryPart(searchResult.getHref()));
159+
}
160+
}
161+
162+
@Override
163+
public void error(IStatus status) {
164+
fail(new RuntimeException(status.getMessage(), status.getException()));
165+
}
166+
167+
};
168+
new LocalHelp().run(query, new LocalHelpScope(null, false), collector, new NullProgressMonitor());
169+
Collections.sort(foundHrefs);
170+
return foundHrefs.toArray(String[]::new);
171+
}
172+
173+
private static String withoutQueryPart(String href) {
174+
return href.indexOf('?') < 0 ? href : href.substring(0, href.indexOf('?'));
175+
}
176+
177+
}

0 commit comments

Comments
 (0)