Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.Iterator;
import java.util.List;

import org.eclipse.help.IHelpResource;
import org.eclipse.help.IToc;
import org.eclipse.help.ITopic;
import org.eclipse.help.base.AbstractHelpScope;
Expand Down Expand Up @@ -297,4 +298,9 @@ private ArrayList<CriterionResource> getCriteriaScopes(WorkingSet[] wSets){
public void addQTCException(QueryTooComplexException exception) throws QueryTooComplexException {
this.searchException = exception;
}

public IHelpResource[] getScopes() {
return scopes == null ? null : scopes.toArray(IHelpResource[]::new);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ public class LocalHelp implements ISearchEngine2 {
public void run(String query, ISearchScope scope,
final ISearchEngineResultCollector collector,
IProgressMonitor monitor) throws CoreException {
String originalQuery = query;

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


// Search
SearchQuery searchQuery = new SearchQuery();
searchQuery.setSearchWord(query);
WorkingSet[] workingSets = null;
LocalHelpScope localScope = (LocalHelpScope) scope;
if (localScope.getWorkingSet() != null)
workingSets = new WorkingSet[] { localScope.getWorkingSet() };
SearchResults localResults = new SearchResults(workingSets, MAX_HITS,
Platform.getNL());
SearchResults localResults = new SearchResults(workingSets, MAX_HITS, Platform.getNL());
// If the indexer has been started and is currently running,
// wait for it to finish.
try {
Job.getJobManager().join(IndexerJob.FAMILY, monitor);
} catch (InterruptedException e) {
}
BaseHelpSystem.getSearchManager().search(searchQuery, localResults,
monitor);
if (!"".equals(query)) { //$NON-NLS-1$
BaseHelpSystem.getSearchManager().search(searchQuery, localResults, monitor);
}

// Post search
ISearchResult results[] = SearchManager.convertHitsToResults(localResults.getSearchHits());
boolean reset = false;
for (AbstractSearchProcessor processor : processors) {
ISearchResult tmp[] = processor.postSearch(query, results);
ISearchResult tmp[] = processor.postSearch(query, originalQuery, results, searchQuery.getLocale(),
localResults.getScopes());
if (tmp!=null)
{
reset = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

package org.eclipse.help.search;

import org.eclipse.help.IHelpResource;

/**
* This class is responsible for handling any pre or post
* search processing events, including query manipulation
Expand All @@ -34,20 +36,52 @@ public AbstractSearchProcessor()
* See {@link SearchProcessorInfo} for types of information that can be used by
* the search display.
*
* @return <code>SearchProcessorInfo</code>, or <code>null</code> for no changes.
* If a {@link SearchProcessorInfo} with an empty, non-{@code null} query
* ({@code ""}) is returned, no search will be executed, resulting in no search
* results.
*
* @return {@link SearchProcessorInfo}, or {@code null} for no changes.
*/
public abstract SearchProcessorInfo preSearch(String query);

/**
* This method is called after the search is performed.
*
* Results are stored as an array of ISearchResult containing
* all available data.
* This method can be used to return a modified result set. For example, one can
* change the result score of an item, add new results to the top of the list,
* or remove results.
*
* This method can be used to return a modified result set. For example, one can change the
* result score of an item, add new results to the top of the list, or remove results.
* This method exists for backwards compatibility. Overwrite
* {@link #postSearch(String, String, ISearchResult[], String, IHelpResource[])}
* if more information like the locale, etc. is needed instead.
*
* @return <code>{@link ISearchResult}[]</code>, or <code>null</code> for no changes.
* @return The modified results, or {@code null} for no changes.
*/
public abstract ISearchResult[] postSearch(String query, ISearchResult[] results);

/**
* This method is called after the search is performed.
*
* This method can be used to return a modified result set. For example, one can
* change the result score of an item, add new results to the top of the list,
* or remove results.
*
* @param query The actually query that was executed (after any changes
* made by {@link #preSearch(String)}).
* @param originalQuery The original query before any changes made by
* {@link #preSearch(String)}.
* @param results The results of the executed query.
* @param results The locale.
* @param results The set scopes (might be {@code null}).
*
* @return The modified results, or {@code null} for no changes.
*
* @see #postSearch(String, ISearchResult[])
*
* @since 4.5
*/
public ISearchResult[] postSearch(String query, String originalQuery, ISearchResult[] results, String locale,
IHelpResource[] scopes) {
return postSearch(query, results);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ private void readDisplayFlags(HttpServletRequest request, HttpServletResponse re
}

public void readSearchResults() {
String originalSearchWord = searchWord;

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

loadSearchResults();
SearchResults searchResults = loadSearchResults();
if (queryException != null) {
return;
}
Expand All @@ -183,9 +184,9 @@ public void readSearchResults() {
ISearchResult results[] = SearchManager.convertHitsToResults(hits);
boolean reset= false;
for (AbstractSearchProcessor processor : processors) {
ISearchResult tmp[] = processor.postSearch(searchWord,results);
if (tmp!=null)
{
ISearchResult tmp[] = processor.postSearch(searchWord, originalSearchWord, results, getLocale(),
searchResults == null ? null : searchResults.getScopes());
if (tmp != null) {
reset = true;
results = tmp;
}
Expand Down Expand Up @@ -438,34 +439,36 @@ private void saveWorkingSet(String workingSet) {
* Call the search engine, and get results or the percentage of indexed
* documents.
*/
private void loadSearchResults() {
private SearchResults loadSearchResults() {
try {
SearchProgressMonitor pm = SearchProgressMonitor
.getProgressMonitor(getLocale());
if (pm.isDone()) {
this.indexCompletion = 100;
SearchResults results = createHitCollector();
BaseHelpSystem.getSearchManager().search(createSearchQuery(),
results, pm);
hits = results.getSearchHits();
if ("".equals(searchWord)) { //$NON-NLS-1$
hits = new SearchHit[0];
} else {
BaseHelpSystem.getSearchManager().search(createSearchQuery(), results, pm);
hits = results.getSearchHits();
}
if (hits == null) {
ILog.of(getClass()).warn("No search results returned. Help index is in use."); //$NON-NLS-1$
}
return;
return results;
}
// progress
indexCompletion = pm.getPercentage();
if (indexCompletion >= 100) {
// 38573 We do not have results, so index cannot be 100
indexCompletion = 100 - 1;
}
return;
} catch (QueryTooComplexException qe) {
queryException = qe;
} catch (Exception e) {
this.indexCompletion = 0;
}

return null;
}

private ISearchQuery createSearchQuery() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2012 IBM Corporation and others.
* Copyright (c) 2006, 2025 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
Expand Down Expand Up @@ -32,6 +32,7 @@
MetaKeywords.class, //
SearchParticipantTest.class, //
SearchParticipantXMLTest.class, //
SearchProcessorTest.class, //
SearchRanking.class, //
WorkingSetManagerTest.class, //
InfocenterWorkingSetManagerTest.class, //
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
/*******************************************************************************
* Copyright (c) 2025 Holger Voormann and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.ua.tests.help.search;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.fail;

import java.util.ArrayList;
import java.util.Collections;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.help.IHelpResource;
import org.eclipse.help.internal.search.SearchQuery;
import org.eclipse.help.internal.search.SearchResult;
import org.eclipse.help.internal.search.federated.LocalHelp;
import org.eclipse.help.internal.search.federated.LocalHelpScope;
import org.eclipse.help.search.AbstractSearchProcessor;
import org.eclipse.help.search.ISearchEngineResult;
import org.eclipse.help.search.ISearchEngineResultCollector;
import org.eclipse.help.search.ISearchResult;
import org.eclipse.help.search.SearchProcessorInfo;
import org.junit.jupiter.api.Test;

public class SearchProcessorTest {

@Test
void testPreSearch() {
var processor = new AbstractSearchProcessor() {

@Override
public SearchProcessorInfo preSearch(String query) {
SearchProcessorInfo info = new SearchProcessorInfo();
info.setQuery("jkijkijkk");
return info;
}

@Override
public ISearchResult[] postSearch(String query, ISearchResult[] results) {
return null;
}

};
test(processor, new String[] { "/org.eclipse.ua.tests/participant1.xml" });
}

@Test
void testPostSearch() {
var processor = new AbstractSearchProcessor() {

@Override
public SearchProcessorInfo preSearch(String query) {
SearchProcessorInfo info = new SearchProcessorInfo();
info.setQuery("jkijkijkk");
return info;
}

@Override
public ISearchResult[] postSearch(String query, ISearchResult[] results) {
assertEquals("jkijkijkk", query);
assertEquals(1, results.length);
assertEquals("/org.eclipse.ua.tests/participant1.xml", withoutQueryPart(results[0].getHref()));
var addedResult = new SearchResult();
addedResult.setHref("/org.eclipse.ua.tests/added");
return new ISearchResult[] { addedResult };
}

};
test(processor, new String[] { "/org.eclipse.ua.tests/added" });
}

@Test
void testExtendedPostSearch() {
var processor = new AbstractSearchProcessor() {

@Override
public SearchProcessorInfo preSearch(String query) {
SearchProcessorInfo info = new SearchProcessorInfo();
info.setQuery("olhoykk");
return info;
}

@Override
public ISearchResult[] postSearch(String query, ISearchResult[] results) {
return null;
}

@Override
public ISearchResult[] postSearch(String query, String originalQuery, ISearchResult[] results,
String locale, IHelpResource[] scopes) {
assertEquals("olhoykk", query);
assertEquals(WrappedSearchProcessor.QUERY, originalQuery);
assertEquals(1, results.length);
assertEquals("/org.eclipse.ua.tests/participant2.xml", withoutQueryPart(results[0].getHref()));
assertEquals(new SearchQuery().getLocale(), locale);
assertNull(scopes);
var addedResult = new SearchResult();
addedResult.setHref("/org.eclipse.ua.tests/added2");
return new ISearchResult[] { addedResult };
}

};
test(processor, new String[] { "/org.eclipse.ua.tests/added2" });
}

@Test
void testNullProcessor() {
var processor = new AbstractSearchProcessor() {

@Override
public SearchProcessorInfo preSearch(String query) {
assertEquals(WrappedSearchProcessor.QUERY, query);
return null;
}

@Override
public ISearchResult[] postSearch(String query, ISearchResult[] results) {
return null;
}

};
test(processor, new String[0]);
}

private void test(AbstractSearchProcessor processor, String[] expected) {
try (var autoClosable = WrappedSearchProcessor.set(processor)) {
String[] hits = search(WrappedSearchProcessor.QUERY);
assertArrayEquals(expected, hits);
} catch (Exception e) {
e.printStackTrace();
fail(e);
}
}

private static String[] search(String query) throws Exception {

var foundHrefs = new ArrayList<String>();
ISearchEngineResultCollector collector = new ISearchEngineResultCollector() {

@Override
public void accept(ISearchEngineResult searchResult) {
foundHrefs.add(withoutQueryPart(searchResult.getHref()));
}

@Override
public void accept(ISearchEngineResult[] searchResults) {
for (ISearchEngineResult searchResult : searchResults) {
foundHrefs.add(withoutQueryPart(searchResult.getHref()));
}
}

@Override
public void error(IStatus status) {
fail(new RuntimeException(status.getMessage(), status.getException()));
}

};
new LocalHelp().run(query, new LocalHelpScope(null, false), collector, new NullProgressMonitor());
Collections.sort(foundHrefs);
return foundHrefs.toArray(String[]::new);
}

private static String withoutQueryPart(String href) {
return href.indexOf('?') < 0 ? href : href.substring(0, href.indexOf('?'));
}

}
Loading
Loading