• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

knowledgepixels / nanodash / 17837235071

18 Sep 2025 05:58PM UTC coverage: 13.87%. Remained the same
17837235071

push

github

tkuhn
chore: Remove serialVersionUIDs

443 of 4022 branches covered (11.01%)

Branch coverage included in aggregate %.

1133 of 7341 relevant lines covered (15.43%)

0.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
src/main/java/com/knowledgepixels/nanodash/page/SearchPage.java
1
package com.knowledgepixels.nanodash.page;
2

3
import java.time.Duration;
4
import java.util.ArrayList;
5
import java.util.HashMap;
6
import java.util.List;
7
import java.util.Map;
8
import java.util.Optional;
9

10
import org.apache.wicket.ajax.AjaxRequestTarget;
11
import org.apache.wicket.ajax.AjaxSelfUpdatingTimerBehavior;
12
import org.apache.wicket.extensions.ajax.markup.html.AjaxLazyLoadPanel;
13
import org.apache.wicket.markup.html.WebMarkupContainer;
14
import org.apache.wicket.markup.html.basic.Label;
15
import org.apache.wicket.markup.html.form.CheckBox;
16
import org.apache.wicket.markup.html.form.Form;
17
import org.apache.wicket.markup.html.form.RadioChoice;
18
import org.apache.wicket.markup.html.form.TextField;
19
import org.apache.wicket.model.Model;
20
import org.apache.wicket.request.mapper.parameter.PageParameters;
21
import org.nanopub.extra.services.ApiResponseEntry;
22
import org.slf4j.Logger;
23
import org.slf4j.LoggerFactory;
24

25
import com.knowledgepixels.nanodash.NanodashPreferences;
26
import com.knowledgepixels.nanodash.NanodashSession;
27
import com.knowledgepixels.nanodash.NanopubElement;
28
import com.knowledgepixels.nanodash.QueryApiAccess;
29
import com.knowledgepixels.nanodash.User;
30
import com.knowledgepixels.nanodash.Utils;
31
import com.knowledgepixels.nanodash.component.NanopubResults;
32
import com.knowledgepixels.nanodash.component.TitleBar;
33

34
/**
35
 * SearchPage allows users to search for nanopublications by URI or free text.
36
 */
37
public class SearchPage extends NanodashPage {
38

39
    private static final Logger logger = LoggerFactory.getLogger(SearchPage.class);
×
40

41
    /**
42
     * The mount path for this page.
43
     */
44
    public static final String MOUNT_PATH = "/search";
45

46
    /**
47
     * {@inheritDoc}
48
     */
49
    @Override
50
    public String getMountPath() {
51
        return MOUNT_PATH;
×
52
    }
53

54
    private TextField<String> searchField;
55
    private CheckBox filterUser;
56
    private Model<String> progress;
57

58
    private Map<String, String> pubKeyMap;
59
    private RadioChoice<String> pubkeySelection;
60

61
    /**
62
     * Constructor for SearchPage.
63
     *
64
     * @param parameters Page parameters containing the search query, filter option, and public key.
65
     */
66
    public SearchPage(final PageParameters parameters) {
67
        super(parameters);
×
68

69
        add(new TitleBar("titlebar", this, "search"));
×
70

71
        final String searchText = parameters.get("query").toString();
×
72
        final Boolean filterCheck = Boolean.valueOf(parameters.get("filter").toString());
×
73
        final String pubkey = parameters.get("pubkey").toString();
×
74

75
        Form<?> form = new Form<Void>("form") {
×
76

77
            protected void onSubmit() {
78
                String searchText = searchField.getModelObject().trim();
×
79
                Boolean filterCheck = filterUser.getModelObject();
×
80
                String pubkey = pubkeySelection.getModelObject();
×
81
                PageParameters params = new PageParameters();
×
82
                params.add("query", searchText);
×
83
                params.add("filter", filterCheck);
×
84
                if (pubkey != null) params.add("pubkey", pubkey);
×
85
                setResponsePage(SearchPage.class, params);
×
86
            }
×
87
        };
88
        add(form);
×
89

90
        form.add(searchField = new TextField<String>("search", Model.of(searchText)));
×
91
        WebMarkupContainer ownFilter = new WebMarkupContainer("own-filter");
×
92
        ownFilter.add(filterUser = new CheckBox("filter", Model.of(filterCheck)));
×
93
        NanodashSession session = NanodashSession.get();
×
94
        ownFilter.setVisible(!NanodashPreferences.get().isReadOnlyMode() && session.getUserIri() != null);
×
95
        ArrayList<String> pubKeyList = new ArrayList<>();
×
96
        if (session.getUserIri() != null) {
×
97
            pubKeyMap = new HashMap<>();
×
98
            String lKeyShort = Utils.getShortPubkeyhashLabel(session.getPubkeyString(), session.getUserIri());
×
99
            pubKeyList.add(lKeyShort);
×
100
            pubKeyMap.put(lKeyShort, session.getPubkeyString());
×
101
            for (String pk : User.getPubkeyhashes(session.getUserIri(), null)) {
×
102
                String keyShort = Utils.getShortPubkeyhashLabel(pk, session.getUserIri());
×
103
                if (!pubKeyMap.containsKey(keyShort)) {
×
104
                    pubKeyList.add(keyShort);
×
105
                    pubKeyMap.put(keyShort, pk);
×
106
                }
107
            }
×
108
        }
109

110
        pubkeySelection = new RadioChoice<String>("pubkeygroup", Model.of(pubkey), pubKeyList);
×
111
        if (!pubKeyList.isEmpty() && pubkeySelection.getModelObject() == null) {
×
112
            pubkeySelection.setDefaultModelObject(pubKeyList.get(0));
×
113
        }
114
        ownFilter.add(pubkeySelection);
×
115

116
        form.add(ownFilter);
×
117

118
        // TODO: Progress bar doesn't update at the moment:
119
        progress = new Model<>();
×
120
        final Label progressLabel = new Label("progress", progress);
×
121
        progressLabel.setOutputMarkupId(true);
×
122
        progressLabel.add(new AjaxSelfUpdatingTimerBehavior(Duration.ofMillis(1000)));
×
123
        add(progressLabel);
×
124

125
        if (searchText == null || searchText.isEmpty()) {
×
126
            add(new Label("nanopubs", "Enter a search term above."));
×
127
        } else {
128
            add(new AjaxLazyLoadPanel<NanopubResults>("nanopubs") {
×
129

130
                @Override
131
                public NanopubResults getLazyLoadComponent(String markupId) {
132
                    Map<String, String> nanopubParams = new HashMap<>();
×
133
                    List<ApiResponseEntry> nanopubResults = new ArrayList<>();
×
134
                    String s = searchText;
×
135
                    if (s != null) {
×
136
                        s = s.trim();
×
137
                        if (s.matches("https?://[^\\s]+")) {
×
138
                            logger.info("URI QUERY: {}", s);
×
139
                            nanopubParams.put("ref", s);
×
140
                            if (Boolean.TRUE.equals(filterCheck)) {
×
141
                                String pubkey = pubKeyMap.get(pubkeySelection.getModelObject());
×
142
                                logger.info("Filter for PUBKEY: {}", pubkey);
×
143
                                nanopubParams.put("pubkey", pubkey);
×
144
                            }
145
                            try {
146
                                // nanopubResults = ApiAccess.getAll("find_nanopubs_with_uri", nanopubParams).getData();
147
                                nanopubResults = QueryApiAccess.get("find-uri-references", nanopubParams).getData();
×
148
                            } catch (Exception ex) {
×
149
                                logger.error("Error while running the query for URI", ex);
×
150
                            }
×
151
//                                                        nanopubResults = ApiAccess.getRecent("find_nanopubs_with_uri", nanopubParams, progress);
152
                        } else {
153
                            String freeTextQuery = getFreeTextQuery(s);
×
154
                            if (!freeTextQuery.isEmpty()) {
×
155
                                logger.info("FREE TEXT QUERY: {}", freeTextQuery);
×
156
                                nanopubParams.put("query", freeTextQuery);
×
157
                                if (filterCheck != null && Boolean.TRUE.equals(filterCheck)) {
×
158
                                    String pubkey = pubKeyMap.get(pubkeySelection.getModelObject());
×
159
                                    logger.info("Filter for PUBKEY: {}", pubkey);
×
160
                                    nanopubParams.put("pubkey", pubkey);
×
161
                                }
162
                                try {
163
                                    // nanopubResults = ApiAccess.getAll("find_nanopubs_with_text", nanopubParams).getData();
164
                                    nanopubResults = QueryApiAccess.get("fulltext-search-on-labels", nanopubParams).getData();
×
165
                                } catch (Exception ex) {
×
166
                                    logger.error("Error during search", ex);
×
167
                                }
×
168
//                                                                nanopubResults = ApiAccess.getRecent("find_nanopubs_with_text", nanopubParams, progress);
169
                            }
170
                        }
171
                    }
172
                    nanopubResults.sort(new ApiResponseEntry.DataComparator());
×
173
                    List<String> nanopubIds = new ArrayList<>();
×
174
                    while (!nanopubResults.isEmpty() && nanopubIds.size() < 100) {
×
175
                        String npUri = nanopubResults.remove(0).get("np");
×
176
                        if (!nanopubIds.contains(npUri)) nanopubIds.add(npUri);
×
177
                    }
×
178
                    progress.setObject("");
×
179
                    if (nanopubIds.isEmpty()) progress.setObject("nothing found");
×
180
                    List<NanopubElement> nanopubs = new ArrayList<>();
×
181
                    for (String id : nanopubIds) nanopubs.add(NanopubElement.get(id));
×
182
                    return NanopubResults.fromList(markupId, nanopubs);
×
183
                }
184

185
                @Override
186
                protected void onContentLoaded(NanopubResults content, Optional<AjaxRequestTarget> target) {
187
                    super.onContentLoaded(content, target);
×
188
                    if (target.isPresent()) {
×
189
                        target.get().appendJavaScript("updateElements();");
×
190
                    }
191
                }
×
192

193
            });
194

195
        }
196
    }
×
197

198
    private static String getFreeTextQuery(String searchText) {
199
        String freeTextQuery = "";
×
200
        String previous = "AND";
×
201
        String preprocessed = "";
×
202
        boolean inQuote = true;
×
203
        for (String s : searchText.replaceAll("\\(\\s+", "(").replaceAll("\\s+\\)", ")").replaceAll("@", "").split("\"")) {
×
204
            inQuote = !inQuote;
×
205
            if (inQuote) {
×
206
                s = "\\\"" + String.join("@", s.split("[^\\p{L}0-9\\-_]+")) + "\\\"";
×
207
            }
208
            preprocessed += s;
×
209
        }
210
        preprocessed = preprocessed.trim();
×
211
        for (String s : preprocessed.split("[^\\p{L}0-9\\-_\\(\\)@\\\"\\\\]+")) {
×
212
            if (s.matches("[0-9].*")) continue;
×
213
            if (!s.matches("AND|OR|\\(+|\\)+|\\(?NOT")) {
×
214
                if (s.toLowerCase().matches("and|or|not")) {
×
215
                    // ignore lower-case and/or/not
216
                    continue;
×
217
                }
218
                if (!previous.matches("AND|OR|\\(?NOT")) {
×
219
                    freeTextQuery += " AND";
×
220
                }
221
            }
222
            freeTextQuery += " " + s.toLowerCase();
×
223
            previous = s;
×
224
        }
225
        freeTextQuery = freeTextQuery.replaceAll("@", " ").trim();
×
226
        return freeTextQuery;
×
227
    }
228

229
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc