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

knowledgepixels / nanodash / 22618039211

03 Mar 2026 10:05AM UTC coverage: 16.058% (+0.2%) from 15.884%
22618039211

Pull #365

github

web-flow
Merge 1e7e700f0 into a8c4b4a77
Pull Request #365: Refactor of `ResourceWithProfile` and related classes

699 of 5287 branches covered (13.22%)

Branch coverage included in aggregate %.

1721 of 9783 relevant lines covered (17.59%)

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

3
import com.knowledgepixels.nanodash.*;
4
import com.knowledgepixels.nanodash.component.ResultComponent;
5
import com.knowledgepixels.nanodash.component.SourceNanopub;
6
import com.knowledgepixels.nanodash.component.TitleBar;
7
import com.knowledgepixels.nanodash.component.ViewList;
8
import com.knowledgepixels.nanodash.domain.AbstractResourceWithProfile;
9
import com.knowledgepixels.nanodash.domain.IndividualAgent;
10
import com.knowledgepixels.nanodash.domain.MaintainedResource;
11
import com.knowledgepixels.nanodash.domain.User;
12
import com.knowledgepixels.nanodash.repository.MaintainedResourceRepository;
13
import com.knowledgepixels.nanodash.repository.SpaceRepository;
14
import org.apache.wicket.Component;
15
import org.apache.wicket.extensions.ajax.markup.html.AjaxLazyLoadPanel;
16
import org.apache.wicket.markup.html.basic.Label;
17
import org.apache.wicket.markup.html.link.AbstractLink;
18
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
19
import org.apache.wicket.model.Model;
20
import org.apache.wicket.request.mapper.parameter.PageParameters;
21
import org.eclipse.rdf4j.model.IRI;
22
import org.eclipse.rdf4j.model.Statement;
23
import org.eclipse.rdf4j.model.util.Values;
24
import org.eclipse.rdf4j.model.vocabulary.DCTERMS;
25
import org.eclipse.rdf4j.model.vocabulary.RDF;
26
import org.eclipse.rdf4j.model.vocabulary.RDFS;
27
import org.eclipse.rdf4j.model.vocabulary.SKOS;
28
import org.nanopub.Nanopub;
29
import org.nanopub.extra.services.ApiResponse;
30
import org.nanopub.extra.services.QueryRef;
31

32
import java.util.ArrayList;
33
import java.util.HashSet;
34
import java.util.List;
35
import java.util.Set;
36

37
/**
38
 * This class represents a page for a resource part in the context of a maintained resource, space, or user.
39
 */
40
public class ResourcePartPage extends NanodashPage {
41

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

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

55
    /**
56
     * Resource with profile (Space or MaintainedResource) object with the data shown on this page.
57
     */
58
    private AbstractResourceWithProfile resourceWithProfile;
59

60
    public ResourcePartPage(final PageParameters parameters) {
61
        super(parameters);
×
62

63
        final String id = parameters.get("id").toString();
×
64
        final String contextId = parameters.get("context").toString();
×
65
        final String nanopubId;
66
        String label = id.replaceFirst("^.*[#/]([^#/]+)$", "$1");
×
67
        String description = null;
×
68
        Set<IRI> classes = new HashSet<>();
×
69

70
        resourceWithProfile = MaintainedResourceRepository.get().findById(contextId);
×
71
        if (resourceWithProfile == null) {
×
72
            if (SpaceRepository.get().findById(contextId) != null) {
×
73
                resourceWithProfile = SpaceRepository.get().findById(contextId);
×
74
            } else if (IndividualAgent.isUser(contextId)) {
×
75
                resourceWithProfile = IndividualAgent.get(contextId);
×
76
            } else {
77
                throw new IllegalArgumentException("Not a resource, space, or user: " + contextId);
×
78
            }
79
        }
80

81
        QueryRef getDefQuery = new QueryRef(QueryApiAccess.GET_TERM_DEFINITIONS, "term", id);
×
82
        if (resourceWithProfile.getSpace() != null) {
×
83
            for (IRI userIri : resourceWithProfile.getSpace().getUsers()) {
×
84
                for (String pubkey : User.getUserData().getPubkeyhashes(userIri, true)) {
×
85
                    getDefQuery.getParams().put("pubkey", pubkey);
×
86
                }
×
87
            }
×
88
        } else {
89
            for (String pubkey : User.getUserData().getPubkeyhashes(Utils.vf.createIRI(contextId), true)) {
×
90
                getDefQuery.getParams().put("pubkey", pubkey);
×
91
            }
×
92
        }
93

94
        ApiResponse getDefResp = ApiCache.retrieveResponseSync(getDefQuery, false);
×
95
        if (getDefResp != null && !getDefResp.getData().isEmpty()) {
×
96
            nanopubId = getDefResp.getData().iterator().next().get("np");
×
97

98
            Nanopub nanopub = Utils.getAsNanopub(nanopubId);
×
99
            for (Statement st : nanopub.getAssertion()) {
×
100
                if (!st.getSubject().stringValue().equals(id)) {
×
101
                    continue;
×
102
                }
103
                if (st.getPredicate().equals(RDFS.LABEL)) {
×
104
                    label = st.getObject().stringValue();
×
105
                }
106
                if (st.getPredicate().equals(SKOS.DEFINITION) || st.getPredicate().equals(DCTERMS.DESCRIPTION) || st.getPredicate().equals(RDFS.COMMENT)) {
×
107
                    description = st.getObject().stringValue();
×
108
                }
109
                if (st.getPredicate().equals(RDF.TYPE) && st.getObject() instanceof IRI objIri) {
×
110
                    classes.add(objIri);
×
111
                }
112
            }
×
113
        } else {
×
114
            nanopubId = null;
×
115
        }
116
//        if (getDefResp == null || getDefResp.getData().isEmpty()) {
117
//            throw new RestartResponseException(ExplorePage.class, parameters);
118
//        }
119

120
        if (description != null) {
×
121
            add(new Label("description", description));
×
122
        } else {
123
            add(new Label("description").setVisible(false));
×
124
        }
125

126
        List<NanodashPageRef> breadCrumb;
127
        if (resourceWithProfile.getSpace() != null) {
×
128
            List<AbstractResourceWithProfile> superSpaces = resourceWithProfile.getSpace().getAllSuperSpacesUntilRoot();
×
129
            if (resourceWithProfile instanceof MaintainedResource) {
×
130
                superSpaces.add(resourceWithProfile.getSpace());
×
131
            }
132
            superSpaces.add(resourceWithProfile);
×
133
            breadCrumb = new ArrayList<>(superSpaces.stream().map(ss -> new NanodashPageRef(SpacePage.class, new PageParameters().add("id", ss.getId()), ss.getLabel())).toList());
×
134
        } else {
×
135
            breadCrumb = new ArrayList<>();
×
136
            breadCrumb.add(new NanodashPageRef(UserPage.class, new PageParameters().add("id", contextId), resourceWithProfile.getLabel()));
×
137
        }
138
        breadCrumb.add(new NanodashPageRef(ResourcePartPage.class, new PageParameters().add("id", id).add("context", contextId).add("label", label), label));
×
139
        NanodashPageRef[] breadCrumbArray = breadCrumb.toArray(new NanodashPageRef[0]);
×
140
        add(new TitleBar("titlebar", this, null,
×
141
                breadCrumbArray
142
        ));
143

144
        add(new Label("pagetitle", label + " (resource part) | nanodash"));
×
145
        add(new Label("name", label));
×
146
        add(new BookmarkablePageLink<Void>("id", ExplorePage.class, parameters.set("label", label)).setBody(Model.of(id)));
×
147
        add(new SourceNanopub("np", nanopubId == null ? Values.iri(id) : Values.iri(nanopubId)));
×
148

149
        // TODO Improve this code, e.g. make Space a subclass of MaintainedResource or otherwise refactor:
150
        // we now use the ProfileResource abstraction, but the code still has to be imprved
151
        if (resourceWithProfile != null) {
×
152
            final List<AbstractLink> viewButtons = new ArrayList<>();
×
153
            AbstractLink addViewButton = new BookmarkablePageLink<NanodashPage>("button", PublishPage.class, new PageParameters()
×
154
                    .set("template", "https://w3id.org/np/RAZg-r7oQjVZ3Ewy7pUzd9eINl6fCa3HGclTsDeRag5to")
×
155
                    .set("template-version", "latest")
×
156
                    .set("param_resource", resourceWithProfile.getId())
×
157
                    .set("context", resourceWithProfile.getId())
×
158
                    .set("part", id)
×
159
            );
160
            addViewButton.setBody(Model.of("+ view display"));
×
161
            viewButtons.add(addViewButton);
×
162

163
            final String nanopubRef = nanopubId == null ? "x:" : nanopubId;
×
164
            final AbstractResourceWithProfile footerResource = resourceWithProfile.getSpace() != null ? resourceWithProfile.getSpace() : resourceWithProfile;
×
165
            if (resourceWithProfile.isDataInitialized()) {
×
166
                add(new ViewList("views", resourceWithProfile, id, nanopubRef, classes, footerResource, viewButtons));
×
167
            } else {
168
                add(new AjaxLazyLoadPanel<Component>("views") {
×
169

170
                    @Override
171
                    public Component getLazyLoadComponent(String markupId) {
172
                        return new ViewList(markupId, resourceWithProfile, id, nanopubRef, classes, footerResource, viewButtons);
×
173
                    }
174

175
                    @Override
176
                    protected boolean isContentReady() {
177
                        return resourceWithProfile.isDataInitialized();
×
178
                    }
179

180
                    @Override
181
                    public Component getLoadingComponent(String id) {
182
                        return new Label(id, "<div class=\"row-section\"><div class=\"col-12\">" + ResultComponent.getWaitIconHtml() + "</div></div>").setEscapeModelStrings(false);
×
183
                    }
184

185
                });
186
            }
187
        } else {
×
188
            // TODO Ugly code duplication (see above):
189

190
            final List<AbstractLink> viewButtons = new ArrayList<>();
×
191
            AbstractLink addViewButton = new BookmarkablePageLink<NanodashPage>("button", PublishPage.class, new PageParameters()
×
192
                    .set("template", "https://w3id.org/np/RAZg-r7oQjVZ3Ewy7pUzd9eINl6fCa3HGclTsDeRag5to")
×
193
                    .set("template-version", "latest")
×
194
                    .set("param_resource", resourceWithProfile.getSpace().getId())
×
195
                    .set("context", resourceWithProfile.getSpace().getId())
×
196
                    .set("part", id)
×
197
            );
198
            addViewButton.setBody(Model.of("+ view display"));
×
199
            viewButtons.add(addViewButton);
×
200

201
            if (resourceWithProfile.getSpace().isDataInitialized()) {
×
202
                add(new ViewList("views", resourceWithProfile.getSpace(), id, nanopubId, classes, resourceWithProfile.getSpace(), viewButtons));
×
203
            } else {
204
                add(new AjaxLazyLoadPanel<Component>("views") {
×
205

206
                    @Override
207
                    public Component getLazyLoadComponent(String markupId) {
208
                        return new ViewList(markupId, resourceWithProfile.getSpace(), id, nanopubId, classes, resourceWithProfile.getSpace(), viewButtons);
×
209
                    }
210

211
                    @Override
212
                    protected boolean isContentReady() {
213
                        return resourceWithProfile.getSpace().isDataInitialized();
×
214
                    }
215

216
                    @Override
217
                    public Component getLoadingComponent(String id) {
218
                        return new Label(id, "<div class=\"row-section\"><div class=\"col-12\">" + ResultComponent.getWaitIconHtml() + "</div></div>").setEscapeModelStrings(false);
×
219
                    }
220

221
                });
222
            }
223
        }
224
    }
×
225

226
    /**
227
     * Checks if auto-refresh is enabled for this page.
228
     *
229
     * @return true if auto-refresh is enabled, false otherwise
230
     */
231
    protected boolean hasAutoRefreshEnabled() {
232
        return true;
×
233
    }
234

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