Skip to content

Commit 1c4c1b5

Browse files
authored
Merge pull request #28 from scijava/remove-duplicate-search-action-labels
Only use highest-priority search result with a given name.
2 parents 9f39739 + 35cb358 commit 1c4c1b5

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

src/main/java/org/scijava/search/SearchService.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929

3030
package org.scijava.search;
3131

32+
import java.util.HashMap;
3233
import java.util.List;
34+
import java.util.Map;
3335
import java.util.stream.Collectors;
3436

3537
import org.scijava.plugin.SingletonService;
@@ -65,9 +67,13 @@ default SearchOperation search(final SearchListener... callbacks) {
6567
* @return A list of actions which could possibly be executed for the result.
6668
*/
6769
default List<SearchAction> actions(final SearchResult result) {
70+
// Create a map used to track whether a name has been seen
71+
final Map<Object, Boolean> seenLabels = new HashMap<>();
6872
return getInstances().stream() //
6973
.filter(factory -> factory.supports(result)) //
7074
.map(factory -> factory.create(result)) //
75+
// NB The following line skip actions with duplicate labels
76+
.filter(t -> seenLabels.putIfAbsent(t.toString(), Boolean.TRUE) == null) //
7177
.collect(Collectors.toList());
7278
}
7379

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
2+
package org.scijava.search.module;
3+
4+
import java.util.List;
5+
6+
import org.junit.Assert;
7+
import org.junit.Before;
8+
import org.junit.Test;
9+
import org.scijava.Context;
10+
import org.scijava.Priority;
11+
import org.scijava.plugin.Plugin;
12+
import org.scijava.search.DefaultSearchAction;
13+
import org.scijava.search.SearchAction;
14+
import org.scijava.search.SearchActionFactory;
15+
import org.scijava.search.SearchResult;
16+
import org.scijava.search.SearchService;
17+
import org.scijava.search.classes.ClassSearchResult;
18+
19+
/**
20+
* Tests that duplicate labels are removed with the {@link SearchService}
21+
*
22+
* @author Gabriel Selzer
23+
*/
24+
public class DuplicateLabelsTest {
25+
26+
/**
27+
* Used to allow the search actions to change state. Run actions can't return
28+
* anything, so we need another way to track that they run.
29+
*/
30+
public static Integer state = 0;
31+
32+
private SearchService searchService;
33+
34+
@Before
35+
public void init() {
36+
Context context = new Context();
37+
searchService = context.getService(SearchService.class);
38+
}
39+
40+
@Test
41+
public void testDuplicateLabelRemoval() {
42+
SearchResult dummyResult = new ClassSearchResult(this.getClass(), "");
43+
List<SearchAction> actions = searchService.actions(dummyResult);
44+
actions.removeIf(a -> !a.toString().equals("test"));
45+
Assert.assertEquals(1, actions.size());
46+
actions.get(0).run();
47+
assert DuplicateLabelsTest.state == 1;
48+
}
49+
50+
@Plugin(type = SearchActionFactory.class, priority = Priority.HIGH)
51+
public static class TestSearchActionFactoryHigh implements
52+
SearchActionFactory
53+
{
54+
55+
@Override
56+
public SearchAction create(SearchResult data) {
57+
return new DefaultSearchAction("test", //
58+
() -> DuplicateLabelsTest.state = 1 //
59+
);
60+
}
61+
}
62+
63+
@Plugin(type = SearchActionFactory.class, priority = Priority.LOW)
64+
public static class TestSearchActionFactoryLow implements
65+
SearchActionFactory
66+
{
67+
68+
@Override
69+
public SearchAction create(SearchResult data) {
70+
return new DefaultSearchAction("test", //
71+
() -> DuplicateLabelsTest.state = 2 //
72+
);
73+
}
74+
75+
}
76+
77+
}

0 commit comments

Comments
 (0)