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

knowledgepixels / nanodash / 17852532121

19 Sep 2025 08:10AM UTC coverage: 13.568% (-0.3%) from 13.87%
17852532121

push

github

tkuhn
feat: Switch to QueryRef provided by nanopub, using multimap

428 of 4008 branches covered (10.68%)

Branch coverage included in aggregate %.

1104 of 7283 relevant lines covered (15.16%)

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/ExplorePage.java
1
package com.knowledgepixels.nanodash.page;
2

3
import java.util.HashMap;
4
import java.util.Map;
5

6
import org.apache.wicket.markup.html.WebMarkupContainer;
7
import org.apache.wicket.markup.html.basic.Label;
8
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
9
import org.apache.wicket.markup.html.link.ExternalLink;
10
import org.apache.wicket.request.flow.RedirectToUrlException;
11
import org.apache.wicket.request.mapper.parameter.PageParameters;
12
import org.commonjava.mimeparse.MIMEParse;
13
import org.nanopub.Nanopub;
14
import org.nanopub.extra.security.SignatureUtils;
15
import org.nanopub.extra.services.ApiResponse;
16
import org.nanopub.extra.services.QueryRef;
17
import org.nanopub.vocabulary.NTEMPLATE;
18
import org.slf4j.Logger;
19
import org.slf4j.LoggerFactory;
20

21
import com.google.common.collect.ArrayListMultimap;
22
import com.google.common.collect.Multimap;
23
import com.knowledgepixels.nanodash.GrlcQuery;
24
import com.knowledgepixels.nanodash.NanopubElement;
25
import com.knowledgepixels.nanodash.QueryApiAccess;
26
import com.knowledgepixels.nanodash.Utils;
27
import com.knowledgepixels.nanodash.component.ExploreDataTable;
28
import com.knowledgepixels.nanodash.component.IriItem;
29
import com.knowledgepixels.nanodash.component.NanopubItem;
30
import com.knowledgepixels.nanodash.component.StatusLine;
31
import com.knowledgepixels.nanodash.component.ThingListPanel;
32
import com.knowledgepixels.nanodash.component.TitleBar;
33

34
import jakarta.servlet.http.HttpServletRequest;
35
import net.trustyuri.TrustyUriUtils;
36

37
/**
38
 * ExplorePage is a page that allows users to explore a specific Nanopublication or Thing.
39
 */
40
public class ExplorePage extends NanodashPage {
41

42
    private static final Logger logger = LoggerFactory.getLogger(ExplorePage.class);
×
43

44
    /**
45
     * The mount path for this page.
46
     */
47
    public static final String MOUNT_PATH = "/explore";
48

49
    /**
50
     * {@inheritDoc}
51
     */
52
    @Override
53
    public String getMountPath() {
54
        return MOUNT_PATH;
×
55
    }
56

57
    /**
58
     * Constructor for ExplorePage.
59
     *
60
     * @param parameters Page parameters containing the ID of the Nanopublication or Thing to explore.
61
     */
62
    public ExplorePage(final PageParameters parameters) {
63
        super(parameters);
×
64

65
        add(new TitleBar("titlebar", this, null));
×
66

67
        String tempRef = parameters.get("id").toString();
×
68

69
        WebMarkupContainer raw = new WebMarkupContainer("raw");
×
70
        add(raw);
×
71

72
        Map<String, String> nanopubParams = new HashMap<>();
×
73
        nanopubParams.put("ref", tempRef);
×
74
        Nanopub np = Utils.getAsNanopub(tempRef);
×
75
        boolean isNanopubId = (np != null);
×
76
        if (isNanopubId) {
×
77
            tempRef = np.getUri().stringValue();
×
78
        }
79
        if (!isNanopubId && tempRef.matches("^(.*[^A-Za-z0-9-_])?RA[A-Za-z0-9-_]{43}[^A-Za-z0-9-_].*$")) {
×
80
            np = Utils.getAsNanopub(tempRef.replaceFirst("^(.*[^A-Za-z0-9-_])?(RA[A-Za-z0-9-_]{43})[^A-Za-z0-9-_].*$", "$2"));
×
81
            if (np != null) {
×
82
                String npId = np.getUri().stringValue();
×
83
                tempRef = npId + tempRef.replaceFirst("^(.*[^A-Za-z0-9-_])?(RA[A-Za-z0-9-_]{43})([^A-Za-z0-9-_].*)$", "$3");
×
84
                Multimap<String, String> params = ArrayListMultimap.create();
×
85
                params.put("thing", tempRef);
×
86
                params.put("np", npId);
×
87
                ApiResponse resp = QueryApiAccess.forcedGet(new QueryRef("get-latest-thing-nanopub", params));
×
88
                if (!resp.getData().isEmpty()) {
×
89
                    // TODO We take the most recent in case more than one latest version exists. Make other latest versions visible too.
90
                    npId = resp.getData().get(0).get("latestVersion");
×
91
                }
92
                np = Utils.getAsNanopub(npId);
×
93
            }
94
        }
95
        if (np == null) {
×
96
            raw.setVisible(false);
×
97
            add(new Label("nanopub-header", ""));
×
98
            add(new Label("nanopub", ""));
×
99
            add(new WebMarkupContainer("use-template").setVisible(false));
×
100
            add(new WebMarkupContainer("run-query").setVisible(false));
×
101
        } else {
102

103
            // Check whether we should redirect to Nanopub Registry for machine-friendly formats:
104
            String mimeType = Utils.TYPE_HTML;
×
105
            try {
106
                HttpServletRequest httpRequest = (HttpServletRequest) getRequest().getContainerRequest();
×
107
                mimeType = MIMEParse.bestMatch(Utils.SUPPORTED_TYPES_LIST, httpRequest.getHeader("Accept"));
×
108
            } catch (Exception ex) {
×
109
                logger.error("Error determining MIME type from Accept header.", ex);
×
110
            }
×
111
            if (!mimeType.equals(Utils.TYPE_HTML)) {
×
112
                logger.info("Non-HTML content type: {}", mimeType);
×
113
                // TODO Make this registry URL configurable/dynamic:
114
                String redirectUrl = Utils.getMainRegistryUrl() + "np/" + TrustyUriUtils.getArtifactCode(np.getUri().stringValue());
×
115
                logger.info("Redirecting to: {}", redirectUrl);
×
116
                throw new RedirectToUrlException(redirectUrl, 302);
×
117
            }
118

119
            String nanopubHeaderLabel = "<h4>%s</h4>";
×
120
            if (isNanopubId) {
×
121
                nanopubHeaderLabel = String.format(nanopubHeaderLabel, "Nanopublication");
×
122
            } else {
123
                nanopubHeaderLabel = String.format(nanopubHeaderLabel, "Minted in Nanopublication");
×
124
            }
125
            add(new Label("nanopub-header", nanopubHeaderLabel).setEscapeModelStrings(false));
×
126
            add(new NanopubItem("nanopub", NanopubElement.get(np)));
×
127
            String url = Utils.getMainRegistryUrl() + "np/" + TrustyUriUtils.getArtifactCode(np.getUri().stringValue());
×
128
            raw.add(new ExternalLink("trig-txt", url + ".trig.txt"));
×
129
            raw.add(new ExternalLink("jsonld-txt", url + ".jsonld.txt"));
×
130
            raw.add(new ExternalLink("nq-txt", url + ".nq.txt"));
×
131
            raw.add(new ExternalLink("xml-txt", url + ".xml.txt"));
×
132
            raw.add(new ExternalLink("trig", url + ".trig"));
×
133
            raw.add(new ExternalLink("jsonld", url + ".jsonld"));
×
134
            raw.add(new ExternalLink("nq", url + ".nq"));
×
135
            raw.add(new ExternalLink("xml", url + ".xml"));
×
136
            if (Utils.isNanopubOfClass(np, NTEMPLATE.ASSERTION_TEMPLATE)) {
×
137
                add(new WebMarkupContainer("use-template").add(new BookmarkablePageLink<Void>("template-link", PublishPage.class, new PageParameters().add("template", np.getUri()))));
×
138
            } else {
139
                add(new WebMarkupContainer("use-template").setVisible(false));
×
140
            }
141
            if (Utils.isNanopubOfClass(np, GrlcQuery.GRLC_QUERY_CLASS)) {
×
142
                add(new WebMarkupContainer("run-query").add(new BookmarkablePageLink<Void>("query-link", QueryPage.class, new PageParameters().add("id", np.getUri()))));
×
143
            } else {
144
                add(new WebMarkupContainer("run-query").setVisible(false));
×
145
            }
146
        }
147

148
        final String ref = tempRef;
×
149
        final String shortName;
150
        if (parameters.get("label").isEmpty()) {
×
151
            shortName = IriItem.getShortNameFromURI(ref);
×
152
        } else {
153
            shortName = parameters.get("label").toString();
×
154
        }
155
        add(new Label("pagetitle", shortName + " (explore) | nanodash"));
×
156
        add(new Label("termname", shortName));
×
157
        add(new ExternalLink("urilink", ref, ref));
×
158
        if (isNanopubId && SignatureUtils.seemsToHaveSignature(np)) {
×
159
            add(StatusLine.createComponent("statusline", ref));
×
160
        } else {
161
            add(new Label("statusline").setVisible(false));
×
162
        }
163
        add(ThingListPanel.createComponent("classes-panel", ThingListPanel.Mode.CLASSES, ref, "<em>Searching for classes...</em>"));
×
164
        if (isNanopubId) {
×
165
            add(new Label("instances-panel").setVisible(false));
×
166
            add(new Label("parts-panel").setVisible(false));
×
167
            add(new Label("templates-panel").setVisible(false));
×
168
        } else {
169
            add(ThingListPanel.createComponent("instances-panel", ThingListPanel.Mode.INSTANCES, ref, "<em>Searching for instances...</em>"));
×
170
            add(ThingListPanel.createComponent("parts-panel", ThingListPanel.Mode.PARTS, ref, "<em>Searching for parts...</em>"));
×
171
            add(ThingListPanel.createComponent("templates-panel", ThingListPanel.Mode.TEMPLATES, ref, "<em>Searching for templates...</em>"));
×
172
        }
173
        add(ExploreDataTable.createComponent("reftable", ref));
×
174
    }
×
175

176
}
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