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

knowledgepixels / nanodash / 24244170325

10 Apr 2026 01:00PM UTC coverage: 16.178% (+0.03%) from 16.147%
24244170325

push

github

web-flow
Merge pull request #433 from knowledgepixels/fix/default-license-not-picked-up

fix: apply user's default license per-request instead of caching globally

789 of 6028 branches covered (13.09%)

Branch coverage included in aggregate %.

1977 of 11069 relevant lines covered (17.86%)

2.44 hits per line

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

0.0
src/main/java/com/knowledgepixels/nanodash/component/PublishForm.java
1
package com.knowledgepixels.nanodash.component;
2

3
import com.knowledgepixels.nanodash.*;
4
import com.knowledgepixels.nanodash.domain.IndividualAgent;
5
import com.knowledgepixels.nanodash.domain.User;
6
import com.knowledgepixels.nanodash.page.*;
7
import com.knowledgepixels.nanodash.repository.MaintainedResourceRepository;
8
import com.knowledgepixels.nanodash.repository.SpaceRepository;
9
import com.knowledgepixels.nanodash.template.*;
10
import org.apache.commons.lang3.Strings;
11
import org.apache.wicket.Component;
12
import org.apache.wicket.RestartResponseException;
13
import org.apache.wicket.ajax.AjaxEventBehavior;
14
import org.apache.wicket.ajax.AjaxRequestTarget;
15
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
16
import org.apache.wicket.feedback.FeedbackMessage;
17
import org.apache.wicket.markup.html.WebMarkupContainer;
18
import org.apache.wicket.markup.html.WebPage;
19
import org.apache.wicket.markup.html.basic.Label;
20
import org.apache.wicket.markup.html.form.Button;
21
import org.apache.wicket.markup.html.form.CheckBox;
22
import org.apache.wicket.markup.html.form.Form;
23
import org.apache.wicket.markup.html.form.FormComponent;
24
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
25
import org.apache.wicket.markup.html.list.ListItem;
26
import org.apache.wicket.markup.html.list.ListView;
27
import org.apache.wicket.markup.html.panel.FeedbackPanel;
28
import org.apache.wicket.markup.html.panel.Panel;
29
import org.apache.wicket.markup.repeater.Item;
30
import org.apache.wicket.markup.repeater.data.DataView;
31
import org.apache.wicket.markup.repeater.data.ListDataProvider;
32
import org.apache.wicket.model.IModel;
33
import org.apache.wicket.model.Model;
34
import org.apache.wicket.request.mapper.parameter.PageParameters;
35
import org.eclipse.rdf4j.model.IRI;
36
import org.eclipse.rdf4j.model.Literal;
37
import org.eclipse.rdf4j.model.Statement;
38
import org.eclipse.rdf4j.model.ValueFactory;
39
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
40
import org.eclipse.rdf4j.model.vocabulary.FOAF;
41
import org.eclipse.rdf4j.model.vocabulary.RDFS;
42
import org.nanopub.MalformedNanopubException;
43
import org.nanopub.Nanopub;
44
import org.nanopub.NanopubAlreadyFinalizedException;
45
import org.nanopub.NanopubCreator;
46
import org.nanopub.extra.security.SignNanopub;
47
import org.nanopub.extra.security.SignatureAlgorithm;
48
import org.nanopub.extra.security.TransformContext;
49
import org.nanopub.extra.server.PublishNanopub;
50
import org.nanopub.extra.services.ApiResponse;
51
import org.nanopub.extra.services.ApiResponseEntry;
52
import org.nanopub.extra.services.QueryRef;
53
import org.nanopub.vocabulary.NPX;
54
import org.nanopub.vocabulary.NTEMPLATE;
55
import org.slf4j.Logger;
56
import org.slf4j.LoggerFactory;
57
import org.wicketstuff.select2.ChoiceProvider;
58
import org.wicketstuff.select2.Response;
59
import org.wicketstuff.select2.Select2Choice;
60

61
import java.lang.reflect.InvocationTargetException;
62
import java.util.*;
63

64
/**
65
 * Form for publishing a nanopublication.
66
 */
67
public class PublishForm extends Panel {
68

69
    private static final Logger logger = LoggerFactory.getLogger(PublishForm.class);
×
70

71
    private static final ValueFactory vf = SimpleValueFactory.getInstance();
×
72

73
    public static final String CREATOR_PUB_INFO_TEMPLATE = "https://w3id.org/np/RAukAcWHRDlkqxk7H2XNSegc1WnHI569INvNr-xdptDGI";
74
    public static final String LICENSE_PUB_INFO_TEMPLATE = "https://w3id.org/np/RACJ58Gvyn91LqCKIO9zu1eijDQIeEff28iyDrJgjSJF8";
75
    public static final String DEFAULT_PROV_TEMPLATE = "https://w3id.org/np/RA7lSq6MuK_TIC6JMSHvLtee3lpLoZDOqLJCLXevnrPoU";
76
    private static final String supersedesPubInfoTemplateId = "https://w3id.org/np/RAoTD7udB2KtUuOuAe74tJi1t3VzK0DyWS7rYVAq1GRvw";
77
    private static final String derivesFromPubInfoTemplateId = "https://w3id.org/np/RARW4MsFkHuwjycNElvEVtuMjpf4yWDL10-0C5l2MqqRQ";
78

79
    private static final String[] fixedPubInfoTemplates = new String[]{CREATOR_PUB_INFO_TEMPLATE, LICENSE_PUB_INFO_TEMPLATE};
×
80

81
    /**
82
     * Fill modes for the nanopublication to be created.
83
     */
84
    public enum FillMode {
×
85
        /**
86
         * Use fill mode
87
         */
88
        USE,
×
89
        /**
90
         * Supersede fill mode
91
         */
92
        SUPERSEDE,
×
93
        /**
94
         * Derive fill mode
95
         */
96
        DERIVE
×
97
    }
98

99
    protected Form<?> form;
100
    protected FeedbackPanel feedbackPanel;
101
    private final TemplateContext assertionContext;
102
    private TemplateContext provenanceContext;
103
    private final List<TemplateContext> pubInfoContexts = new ArrayList<>();
×
104
    private final Map<String, TemplateContext> pubInfoContextMap = new HashMap<>();
×
105
    private final List<TemplateContext> requiredPubInfoContexts = new ArrayList<>();
×
106
    private String targetNamespace;
107
    private final Class<? extends WebPage> confirmPageClass;
108

109
    /**
110
     * Constructor for the PublishForm.
111
     *
112
     * @param id               the Wicket component ID
113
     * @param pageParams       the parameters for the page, which may include information on how to fill the form
114
     * @param publishPageClass the class of the page to redirect to after successful publication
115
     * @param confirmPageClass the class of the confirmation page to show after publication
116
     */
117
    public PublishForm(String id, final PageParameters pageParams, Class<? extends WebPage> publishPageClass, Class<? extends WebPage> confirmPageClass) {
118
        super(id);
×
119
        setOutputMarkupId(true);
×
120
        this.confirmPageClass = confirmPageClass;
×
121

122
        WebMarkupContainer linkMessageItem = new WebMarkupContainer("link-message-item");
×
123
        if (pageParams.get("link-message").isNull()) {
×
124
            linkMessageItem.add(new Label("link-message", ""));
×
125
            linkMessageItem.setVisible(false);
×
126
        } else {
127
            linkMessageItem.add(new Label("link-message", Utils.sanitizeHtml(pageParams.get("link-message").toString())).setEscapeModelStrings(false));
×
128
        }
129
        add(linkMessageItem);
×
130

131
        final Nanopub fillNp;
132
        final FillMode fillMode;
133
        boolean fillOnlyAssertion = false;
×
134
        if (!pageParams.get("use").isNull()) {
×
135
            fillNp = Utils.getNanopub(pageParams.get("use").toString());
×
136
            fillMode = FillMode.USE;
×
137
        } else if (!pageParams.get("use-a").isNull()) {
×
138
            fillNp = Utils.getNanopub(pageParams.get("use-a").toString());
×
139
            fillMode = FillMode.USE;
×
140
            fillOnlyAssertion = true;
×
141
        } else if (!pageParams.get("supersede").isNull()) {
×
142
            fillNp = Utils.getNanopub(pageParams.get("supersede").toString());
×
143
            fillMode = FillMode.SUPERSEDE;
×
144
            targetNamespace = pageParams.get("supersede").toString().replaceFirst("RA[A-Za-z0-9-_]{43}$", "");
×
145
        } else if (!pageParams.get("supersede-a").isNull()) {
×
146
            fillNp = Utils.getNanopub(pageParams.get("supersede-a").toString());
×
147
            fillMode = FillMode.SUPERSEDE;
×
148
            fillOnlyAssertion = true;
×
149
        } else if (!pageParams.get("derive").isNull()) {
×
150
            fillNp = Utils.getNanopub(pageParams.get("derive").toString());
×
151
            fillMode = FillMode.DERIVE;
×
152
        } else if (!pageParams.get("derive-a").isNull()) {
×
153
            fillNp = Utils.getNanopub(pageParams.get("derive-a").toString());
×
154
            fillMode = FillMode.DERIVE;
×
155
            fillOnlyAssertion = true;
×
156
        } else if (!pageParams.get("fill-all").isNull()) {
×
157
            // TODO: This is deprecated and should be removed at some point
158
            fillNp = Utils.getNanopub(pageParams.get("fill-all").toString());
×
159
            fillMode = FillMode.USE;
×
160
        } else if (!pageParams.get("fill").isNull()) {
×
161
            // TODO: This is deprecated and should be removed at some point
162
            fillNp = Utils.getNanopub(pageParams.get("fill").toString());
×
163
            fillMode = FillMode.SUPERSEDE;
×
164
        } else {
165
            fillNp = null;
×
166
            fillMode = null;
×
167
        }
168

169
        final TemplateData td = TemplateData.get();
×
170

171
        // TODO Properly integrate this namespace feature:
172
        String templateId = pageParams.get("template").toString();
×
173
        if (td.getTemplate(templateId).getTargetNamespace() != null) {
×
174
            targetNamespace = td.getTemplate(templateId).getTargetNamespace();
×
175
        }
176
        if (!pageParams.get("target-namespace").isNull()) {
×
177
            targetNamespace = pageParams.get("target-namespace").toString();
×
178
        }
179
        if (targetNamespace == null) {
×
180
            targetNamespace = Template.DEFAULT_TARGET_NAMESPACE;
×
181
        }
182
        String targetNamespaceLabel = targetNamespace + "...";
×
183
        targetNamespace = targetNamespace + "~~~ARTIFACTCODE~~~/";
×
184

185
        assertionContext = new TemplateContext(ContextType.ASSERTION, templateId, "statement", targetNamespace);
×
186
        assertionContext.setFillMode(fillMode);
×
187
        final String prTemplateId;
188
        if (pageParams.get("prtemplate").toString() != null) {
×
189
            prTemplateId = pageParams.get("prtemplate").toString();
×
190
        } else {
191
            if (fillNp != null && !fillOnlyAssertion) {
×
192
                if (td.getProvenanceTemplateId(fillNp) != null) {
×
193
                    prTemplateId = td.getProvenanceTemplateId(fillNp).stringValue();
×
194
                } else {
195
                    prTemplateId = "http://purl.org/np/RAcm8OurwUk15WOgBM9wySo-T3a5h6as4K8YR5MBrrxUc";
×
196
                }
197
            } else if (assertionContext.getTemplate().getDefaultProvenance() != null) {
×
198
                prTemplateId = assertionContext.getTemplate().getDefaultProvenance().stringValue();
×
199
            } else {
200
                prTemplateId = DEFAULT_PROV_TEMPLATE;
×
201
            }
202
        }
203
        provenanceContext = new TemplateContext(ContextType.PROVENANCE, prTemplateId, "pr-statement", targetNamespace);
×
204
        for (String t : fixedPubInfoTemplates) {
×
205
            // TODO consistently check for latest versions of templates here and below:
206
            TemplateContext c = new TemplateContext(ContextType.PUBINFO, t, "pi-statement", targetNamespace);
×
207
            pubInfoContexts.add(c);
×
208
            pubInfoContextMap.put(c.getTemplate().getId(), c);
×
209
            requiredPubInfoContexts.add(c);
×
210
            if (t.equals(LICENSE_PUB_INFO_TEMPLATE)) {
×
211
                IRI defaultLicense = User.getDefaultLicense(NanodashSession.get().getUserIri());
×
212
                if (defaultLicense != null) {
×
213
                    c.setParam("license", defaultLicense.stringValue());
×
214
                }
215
            }
216
        }
217
        if (fillMode == FillMode.SUPERSEDE) {
×
218
            TemplateContext c = new TemplateContext(ContextType.PUBINFO, supersedesPubInfoTemplateId, "pi-statement", targetNamespace);
×
219
            pubInfoContexts.add(c);
×
220
            pubInfoContextMap.put(supersedesPubInfoTemplateId, c);
×
221
            //requiredPubInfoContexts.add(c);
222
            c.setParam("np", fillNp.getUri().stringValue());
×
223
        } else if (fillMode == FillMode.DERIVE) {
×
224
            TemplateContext c = new TemplateContext(ContextType.PUBINFO, derivesFromPubInfoTemplateId, "pi-statement", targetNamespace);
×
225
            pubInfoContexts.add(c);
×
226
            pubInfoContextMap.put(derivesFromPubInfoTemplateId, c);
×
227
            c.setParam("np", fillNp.getUri().stringValue());
×
228
        }
229
        for (IRI r : assertionContext.getTemplate().getRequiredPubInfoElements()) {
×
230
            String latestId = QueryApiAccess.getLatestVersionId(r.stringValue());
×
231
            if (pubInfoContextMap.containsKey(r.stringValue()) || pubInfoContextMap.containsKey(latestId)) continue;
×
232
            TemplateContext c = new TemplateContext(ContextType.PUBINFO, r.stringValue(), "pi-statement", targetNamespace);
×
233
            pubInfoContexts.add(c);
×
234
            pubInfoContextMap.put(c.getTemplateId(), c);
×
235
            requiredPubInfoContexts.add(c);
×
236
        }
×
237
        Map<Integer, TemplateContext> piParamIdMap = new HashMap<>();
×
238
        for (String k : pageParams.getNamedKeys()) {
×
239
            if (!k.matches("pitemplate[1-9][0-9]*")) continue;
×
240
            Integer i = Integer.parseInt(k.replaceFirst("^pitemplate([1-9][0-9]*)$", "$1"));
×
241
            String tid = pageParams.get(k).toString();
×
242
            // TODO Allow for automatically using latest template version:
243
            //String piTemplateIdLatest = QueryApiAccess.getLatestVersionId(tid);
244
            TemplateContext c = createPubInfoContext(tid);
×
245
            if (piParamIdMap.containsKey(i)) {
×
246
                // TODO: handle this error better
247
                logger.error("Publication Info template param identifier defined multiple times: {}", i);
×
248
            }
249
            piParamIdMap.put(i, c);
×
250
        }
×
251
        if (fillNp != null && !fillOnlyAssertion) {
×
252
            for (IRI piTemplateId : td.getPubinfoTemplateIds(fillNp)) {
×
253
                String piTemplateIdLatest = QueryApiAccess.getLatestVersionId(piTemplateId.stringValue());
×
254
                if (piTemplateIdLatest.equals(supersedesPubInfoTemplateId)) continue;
×
255
                if (!pubInfoContextMap.containsKey(piTemplateIdLatest)) {
×
256
                    // TODO Allow for automatically using latest template version
257
                    createPubInfoContext(piTemplateId.stringValue());
×
258
                }
259
            }
×
260
        }
261
        if (!pageParams.get("values-from-query").isEmpty() && !pageParams.get("values-from-query-mapping").isEmpty()) {
×
262
            String querySpec = pageParams.get("values-from-query").toString();
×
263

264
            String mapping = pageParams.get("values-from-query-mapping").toString();
×
265
            String mapsFrom, mapsTo;
266
            if (mapping.contains(":")) {
×
267
                mapsFrom = mapping.split(":")[0];
×
268
                mapsTo = mapping.split(":")[1];
×
269
            } else {
270
                mapsFrom = mapping;
×
271
                mapsTo = mapping;
×
272
            }
273
            ApiResponse resp = ApiCache.retrieveResponseSync(QueryRef.parseString(querySpec), false);
×
274
            int i = 0;
×
275
            for (ApiResponseEntry e : resp.getData()) {
×
276
                String mapsToSuffix = "";
×
277
                if (i > 0) mapsToSuffix = "__" + i;
×
278
                assertionContext.setParam(mapsTo + mapsToSuffix, e.get(mapsFrom));
×
279
                i++;
×
280
            }
×
281
        }
282
        for (String k : pageParams.getNamedKeys()) {
×
283
            if (k.startsWith("param_")) assertionContext.setParam(k.substring(6), pageParams.get(k).toString());
×
284
            if (k.startsWith("prparam_")) provenanceContext.setParam(k.substring(8), pageParams.get(k).toString());
×
285
            if (k.matches("piparam[1-9][0-9]*_.*")) {
×
286
                Integer i = Integer.parseInt(k.replaceFirst("^piparam([1-9][0-9]*)_.*$", "$1"));
×
287
                if (!piParamIdMap.containsKey(i)) {
×
288
                    logger.error("Parameter {} of the publication info template not found", i);
×
289
                    continue;
×
290
                }
291
                String n = k.replaceFirst("^piparam[1-9][0-9]*_(.*)$", "$1");
×
292
                logger.info(n);
×
293
                piParamIdMap.get(i).setParam(n, pageParams.get(k).toString());
×
294
            }
295
        }
×
296

297
        // Init statements only now, in order to pick up parameter values:
298
        assertionContext.initStatements();
×
299
        provenanceContext.initStatements();
×
300
        for (TemplateContext c : pubInfoContexts) {
×
301
            c.initStatements();
×
302
        }
×
303

304
        String latestAssertionId = QueryApiAccess.getLatestVersionId(assertionContext.getTemplateId());
×
305
        if (!assertionContext.getTemplateId().equals(latestAssertionId)) {
×
306
            add(new Label("newversion", "There is a new version of this assertion template:"));
×
307
            PageParameters params = new PageParameters(pageParams);
×
308
            params.set("template", latestAssertionId).remove("formobj");
×
309
            add(new BookmarkablePageLink<Void>("newversionlink", publishPageClass, params));
×
310
            if ("latest".equals(pageParams.get("template-version").toString())) {
×
311
                throw new RestartResponseException(publishPageClass, params);
×
312
            }
313
        } else {
×
314
            add(new Label("newversion", "").setVisible(false));
×
315
            add(new Label("newversionlink", "").setVisible(false));
×
316
        }
317

318
        final Nanopub improveNp;
319
        if (!pageParams.get("improve").isNull()) {
×
320
            improveNp = Utils.getNanopub(pageParams.get("improve").toString());
×
321
        } else {
322
            improveNp = null;
×
323
        }
324

325
        final List<Statement> unusedStatementList = new ArrayList<>();
×
326
        final List<Statement> unusedPrStatementList = new ArrayList<>();
×
327
        final List<Statement> unusedPiStatementList = new ArrayList<>();
×
328
        if (fillNp != null) {
×
329
            ValueFiller filler = new ValueFiller(fillNp, ContextType.ASSERTION, true, fillMode);
×
330
            filler.fill(assertionContext);
×
331
            unusedStatementList.addAll(filler.getUnusedStatements());
×
332

333
            if (!fillOnlyAssertion) {
×
334
                ValueFiller prFiller = new ValueFiller(fillNp, ContextType.PROVENANCE, true);
×
335
                prFiller.fill(provenanceContext);
×
336
                unusedPrStatementList.addAll(prFiller.getUnusedStatements());
×
337

338
                ValueFiller piFiller = new ValueFiller(fillNp, ContextType.PUBINFO, true);
×
339
                if (!assertionContext.getTemplate().getTargetNanopubTypes().isEmpty()) {
×
340
                    for (Statement st : new ArrayList<>(piFiller.getUnusedStatements())) {
×
341
                        if (st.getSubject().stringValue().equals(LocalUri.of("nanopub").stringValue()) && st.getPredicate().equals(NPX.HAS_NANOPUB_TYPE)) {
×
342
                            if (assertionContext.getTemplate().getTargetNanopubTypes().contains(st.getObject())) {
×
343
                                piFiller.removeUnusedStatement(st);
×
344
                            }
345
                        }
346
                    }
×
347
                }
348
                for (TemplateContext c : pubInfoContexts) {
×
349
                    piFiller.fill(c);
×
350
                }
×
351
                piFiller.removeUnusedStatements(NanodashSession.get().getUserIri(), FOAF.NAME, null);
×
352
                if (piFiller.hasUnusedStatements()) {
×
353
                    final String handcodedStatementsTemplateId = "https://w3id.org/np/RAMEgudZsQ1bh1fZhfYnkthqH6YSXpghSE_DEN1I-6eAI";
×
354
                    if (!pubInfoContextMap.containsKey(handcodedStatementsTemplateId)) {
×
355
                        TemplateContext c = createPubInfoContext(handcodedStatementsTemplateId);
×
356
                        c.initStatements();
×
357
                        piFiller.fill(c);
×
358
                    }
359
                }
360
                unusedPiStatementList.addAll(piFiller.getUnusedStatements());
×
361
                // TODO: Also use pubinfo templates stated in nanopub to be filled in?
362
//                                Set<IRI> pubinfoTemplateIds = Template.getPubinfoTemplateIds(fillNp);
363
//                                if (!pubinfoTemplateIds.isEmpty()) {
364
//                                        ValueFiller piFiller = new ValueFiller(fillNp, ContextType.PUBINFO);
365
//                                        for (IRI pubinfoTemplateId : pubinfoTemplateIds) {
366
//                                                // TODO: Make smart choice on the ordering in trying to fill in all pubinfo elements
367
//                                                piFiller.fill(pubInfoContextMap.get(pubinfoTemplateId.stringValue()));
368
//                                        }
369
//                                        warningMessage += (piFiller.getWarningMessage() == null ? "" : "Publication info: " + piFiller.getWarningMessage() + " ");
370
//                                }
371
            }
372
        } else if (improveNp != null) {
×
373
            ValueFiller filler = new ValueFiller(improveNp, ContextType.ASSERTION, true);
×
374
            filler.fill(assertionContext);
×
375
            unusedStatementList.addAll(filler.getUnusedStatements());
×
376
        }
377
        if (!unusedStatementList.isEmpty()) {
×
378
            add(new Label("warnings", "Some content from the existing nanopublication could not be filled in:"));
×
379
        } else {
380
            add(new Label("warnings", "").setVisible(false));
×
381
        }
382
        add(new DataView<Statement>("unused-statements", new ListDataProvider<Statement>(unusedStatementList)) {
×
383

384
            @Override
385
            protected void populateItem(Item<Statement> item) {
386
                item.add(new TripleItem("unused-statement", item.getModelObject(), (fillNp != null ? fillNp : improveNp), null));
×
387
            }
×
388

389
        });
390
        add(new DataView<Statement>("unused-prstatements", new ListDataProvider<Statement>(unusedPrStatementList)) {
×
391

392
            @Override
393
            protected void populateItem(Item<Statement> item) {
394
                item.add(new TripleItem("unused-prstatement", item.getModelObject(), (fillNp != null ? fillNp : improveNp), null));
×
395
            }
×
396

397
        });
398
        add(new DataView<Statement>("unused-pistatements", new ListDataProvider<Statement>(unusedPiStatementList)) {
×
399

400
            @Override
401
            protected void populateItem(Item<Statement> item) {
402
                item.add(new TripleItem("unused-pistatement", item.getModelObject(), (fillNp != null ? fillNp : improveNp), null));
×
403
            }
×
404

405
        });
406

407
        // Finalize statements, which picks up parameter values in repetitions:
408
        assertionContext.finalizeStatements();
×
409
        provenanceContext.finalizeStatements();
×
410
        for (TemplateContext c : pubInfoContexts) {
×
411
            c.finalizeStatements();
×
412
        }
×
413

414
        final CheckBox consentCheck = new CheckBox("consentcheck", new Model<>(false));
×
415
        consentCheck.add(new InvalidityHighlighting());
×
416

417
        form = new Form<Void>("form") {
×
418

419
            @Override
420
            protected void onConfigure() {
421
                super.onConfigure();
×
422
                form.getFeedbackMessages().clear();
×
423
//                                formComponents.clear();
424
            }
×
425

426
            protected void onSubmit() {
427
                if (!Boolean.TRUE.equals(consentCheck.getModelObject())) {
×
428
                    feedbackPanel.error("You need to check the checkbox that you understand the consequences.");
×
429
                    return;
×
430
                }
431
                logger.info("Publish form submitted");
×
432
                Nanopub signedNp;
433
                try {
434
                    Nanopub np = createNanopub();
×
435
                    logger.info("Nanopublication created: {}", np.getUri());
×
436
                    TransformContext tc = new TransformContext(SignatureAlgorithm.RSA, NanodashSession.get().getKeyPair(), NanodashSession.get().getUserIri(), false, false, false);
×
437
                    signedNp = SignNanopub.signAndTransform(np, tc);
×
438
                    logger.info("Nanopublication signed: {}", signedNp.getUri());
×
439
                    String npUrl = PublishNanopub.publish(signedNp, Utils.getMainRegistryUrl());
×
440
                    logger.info("Nanopublication published: {}", npUrl);
×
441
                    Utils.cacheNanopub(signedNp);
×
442
                } catch (Exception ex) {
×
443
                    signedNp = null;
×
444
                    logger.error("Nanopublication publishing failed: {}", ex.getMessage());
×
445
                    String message = ex.getClass().getName();
×
446
                    if (ex.getMessage() != null) {
×
447
                        message = ex.getMessage();
×
448
                    }
449
                    feedbackPanel.error(message);
×
450
                }
×
451
                if (signedNp != null) {
×
452
                    if (!pageParams.get("refresh-upon-publish").isEmpty()) {
×
453
                        String toRefresh = pageParams.get("refresh-upon-publish").toString();
×
454
                        WicketApplication.get().notifyNanopubPublished(signedNp, toRefresh, 5 * 1000);
×
455
                    }
456
                    String contextId = pageParams.get("context").toString("");
×
457
                    String partId = pageParams.get("part").toString("");
×
458
                    if (!contextId.isEmpty() && pageParams.get("postpub-redirect-url").isEmpty()) {
×
459
                        PageParameters redirectParams = new PageParameters().set("just-published", signedNp.getUri().stringValue());
×
460
                        if (!partId.isEmpty()) {
×
461
                            // User was on a part page (e.g. paper collection); redirect back to the part page
462
                            redirectParams.set("id", partId).set("context", contextId);
×
463
                            throw new RestartResponseException(ResourcePartPage.class, redirectParams);
×
464
                        }
465
                        redirectParams.set("id", contextId);
×
466
                        if (SpaceRepository.get().findById(contextId) != null) {
×
467
                            throw new RestartResponseException(SpacePage.class, redirectParams);
×
468
                        }
469
                        if (MaintainedResourceRepository.get().findById(contextId) != null) {
×
470
                            throw new RestartResponseException(MaintainedResourcePage.class, redirectParams);
×
471
                        }
472
                        if (IndividualAgent.isUser(contextId)) {
×
473
                            throw new RestartResponseException(UserPage.class, redirectParams);
×
474
                        }
475
                    }
476
                    NanodashPage confirmPage = getConfirmPage(signedNp, pageParams);
×
477
                    if (confirmPage != null) {
×
478
                        throw new RestartResponseException(confirmPage);
×
479
                    }
480
                    throw new RestartResponseException(ExplorePage.class,
×
481
                            new PageParameters(pageParams).set("id", signedNp.getUri().stringValue()));
×
482
                }
483
            }
×
484

485
            @Override
486
            protected void onValidate() {
487
                super.onValidate();
×
488
                for (Component fc : assertionContext.getComponents()) {
×
489
                    processFeedback(fc);
×
490
                }
×
491
                for (Component fc : provenanceContext.getComponents()) {
×
492
                    processFeedback(fc);
×
493
                }
×
494
                for (TemplateContext c : pubInfoContexts) {
×
495
                    for (Component fc : c.getComponents()) {
×
496
                        processFeedback(fc);
×
497
                    }
×
498
                }
×
499
            }
×
500

501
            private void processFeedback(Component c) {
502
                if (c instanceof FormComponent) {
×
503
                    ((FormComponent<?>) c).processInput();
×
504
                }
505
                for (FeedbackMessage fm : c.getFeedbackMessages()) {
×
506
                    form.getFeedbackMessages().add(fm);
×
507
                }
×
508
            }
×
509

510
        };
511
        form.setOutputMarkupId(true);
×
512

513
        //form.add(new Label("nanopub-namespace", targetNamespaceLabel));
514

515
        form.add(new BookmarkablePageLink<Void>("templatelink", ExplorePage.class, new PageParameters().set("id", assertionContext.getTemplate().getId())));
×
516
        form.add(new Label("templatename", assertionContext.getTemplate().getLabel()));
×
517
        String description = assertionContext.getTemplate().getLabel();
×
518
        form.add(new Label("templatedesc", assertionContext.getTemplate().getDescription()).setEscapeModelStrings(false));
×
519

520
        form.add(new ListView<StatementItem>("statements", assertionContext.getStatementItems()) {
×
521

522
            protected void populateItem(ListItem<StatementItem> item) {
523
                item.add(item.getModelObject());
×
524
            }
×
525

526
        });
527

528
        final Map<String, Boolean> handledProvTemplates = new HashMap<>();
×
529
        final String defaultProvTemplateId;
530
        if (assertionContext.getTemplate().getDefaultProvenance() != null) {
×
531
            defaultProvTemplateId = assertionContext.getTemplate().getDefaultProvenance().stringValue();
×
532
            handledProvTemplates.put(defaultProvTemplateId, true);
×
533
        } else {
534
            defaultProvTemplateId = null;
×
535
        }
536
        final List<String> recommendedProvTemplateOptionIds = new ArrayList<>();
×
537
        final List<String> provTemplateOptionIds = new ArrayList<>();
×
538
        if (pageParams.get("prtemplate-options").isNull()) {
×
539
            // TODO Make this dynamic and consider updated templates:
540
            recommendedProvTemplateOptionIds.add(DEFAULT_PROV_TEMPLATE);
×
541
            recommendedProvTemplateOptionIds.add("http://purl.org/np/RAcTpoh5Ra0ssqmcpOgWdaZ_YiPE6demO6cpw-2RvSNs8");
×
542
            recommendedProvTemplateOptionIds.add("http://purl.org/np/RA4LGtuOqTIMqVAkjnfBXk1YDcAPNadP5CGiaJiBkdHCQ");
×
543
            recommendedProvTemplateOptionIds.add("http://purl.org/np/RAl_-VTw9Re_uRF8r8y0rjlfnu7FlhTa8xg_8xkcweqiE");
×
544
            recommendedProvTemplateOptionIds.add("https://w3id.org/np/RASORV2mMEVpS4lWh2bwUTEcV-RWjbD9RPbN7J0PIeYAU");
×
545
            recommendedProvTemplateOptionIds.add("http://purl.org/np/RAjkBbM5yQm7hKH1l_Jk3HAUqWi3Bd57TPmAOZCsZmi_M");
×
546
            recommendedProvTemplateOptionIds.add("http://purl.org/np/RAGXx_k9eQMnXaCbsXMsJbGClwZtQEGNg0GVJu6amdAVw");
×
547
            recommendedProvTemplateOptionIds.add("http://purl.org/np/RA1fnITI3Pu1UQ0CHghNpys3JwQrM32LBnjmDLoayp9-4");
×
548
            recommendedProvTemplateOptionIds.add("http://purl.org/np/RAJgbsGeGdTG-zq_gU0TLw4s3raMgoRk-mPlc2DSLXvE0");
×
549
            recommendedProvTemplateOptionIds.add("http://purl.org/np/RA6SXfhUY-xeblZU8HhPddw6tsu-C5NXevG6C_zv4bMxU");
×
550
            for (String s : recommendedProvTemplateOptionIds) {
×
551
                handledProvTemplates.put(s, true);
×
552
            }
×
553

554
            for (ApiResponseEntry t : td.getProvenanceTemplates()) {
×
555
                String tid = t.get("np");
×
556
                if (handledProvTemplates.containsKey(tid)) continue;
×
557
                provTemplateOptionIds.add(tid);
×
558
                handledProvTemplates.put(tid, true);
×
559
            }
×
560
        } else {
561
            for (String s : pageParams.get("prtemplate-options").toString().split(" ")) {
×
562
                if (handledProvTemplates.containsKey(s)) continue;
×
563
                recommendedProvTemplateOptionIds.add(s);
×
564
                handledProvTemplates.put(s, true);
×
565
            }
566
        }
567

568
        ChoiceProvider<String> prTemplateChoiceProvider = new ChoiceProvider<String>() {
×
569

570
            @Override
571
            public String getDisplayValue(String object) {
572
                if (object == null || object.isEmpty()) return "";
×
573
                Template t = td.getTemplate(object);
×
574
                if (t != null) return t.getLabel();
×
575
                return object;
×
576
            }
577

578
            @Override
579
            public String getIdValue(String object) {
580
                return object;
×
581
            }
582

583
            // Getting strange errors with Tomcat if this method is not overridden:
584
            @Override
585
            public void detach() {
586
            }
×
587

588
            @Override
589
            public void query(String term, int page, Response<String> response) {
590
                if (term == null) term = "";
×
591
                term = term.toLowerCase();
×
592
                if (pageParams.get("prtemplate").toString() != null) {
×
593
                    // Using this work-around with "——" because 'optgroup' is not available through Wicket's Select2 classes
594
                    response.add("—— default for this link ——");
×
595
                    response.add(prTemplateId);
×
596
                }
597
                if (defaultProvTemplateId != null) {
×
598
                    response.add("—— default for this template ——");
×
599
                    response.add(defaultProvTemplateId);
×
600
                }
601
                if (!recommendedProvTemplateOptionIds.isEmpty()) {
×
602
                    if (pageParams.get("prtemplate-options").isNull()) {
×
603
                        response.add("—— recommended ——");
×
604
                    }
605
                    for (String s : recommendedProvTemplateOptionIds) {
×
606
                        if (s.toLowerCase().contains(term) || getDisplayValue(s).toLowerCase().contains(term)) {
×
607
                            response.add(s);
×
608
                        }
609
                    }
×
610
                }
611
                if (!provTemplateOptionIds.isEmpty()) {
×
612
                    response.add("—— others ——");
×
613
                    for (String s : provTemplateOptionIds) {
×
614
                        if (s.toLowerCase().contains(term) || getDisplayValue(s).toLowerCase().contains(term)) {
×
615
                            response.add(s);
×
616
                        }
617
                    }
×
618
                }
619
            }
×
620

621
            @Override
622
            public Collection<String> toChoices(Collection<String> ids) {
623
                return ids;
×
624
            }
625

626
        };
627
        final IModel<String> prTemplateModel = Model.of(provenanceContext.getTemplate().getId());
×
628
        Select2Choice<String> prTemplateChoice = new Select2Choice<String>("prtemplate", prTemplateModel, prTemplateChoiceProvider);
×
629
        prTemplateChoice.setRequired(true);
×
630
        prTemplateChoice.getSettings().setCloseOnSelect(true);
×
631
        prTemplateChoice.add(new AjaxFormComponentUpdatingBehavior("change") {
×
632

633
            @Override
634
            protected void onUpdate(AjaxRequestTarget target) {
635
                String o = prTemplateModel.getObject();
×
636
                if (o.startsWith("——")) {
×
637
                    o = provenanceContext.getTemplate().getId();
×
638
                    prTemplateModel.setObject(o);
×
639
                }
640
                provenanceContext = new TemplateContext(ContextType.PROVENANCE, prTemplateModel.getObject(), "pr-statement", targetNamespace);
×
641
                provenanceContext.initStatements();
×
642
                refreshProvenance(target);
×
643
                provenanceContext.finalizeStatements();
×
644
            }
×
645

646
        });
647
        form.add(prTemplateChoice);
×
648
        refreshProvenance(null);
×
649

650
        final Map<String, Boolean> handledPiTemplates = new HashMap<>();
×
651
        final List<String> recommendedPiTemplateOptionIds = new ArrayList<>();
×
652
        final List<String> piTemplateOptionIds = new ArrayList<>();
×
653
        // TODO Make this dynamic and consider updated templates:
654
        recommendedPiTemplateOptionIds.add("http://purl.org/np/RAXflINqt3smqxV5Aq7E9lzje4uLdkKIOefa6Bp8oJ8CY");
×
655
        recommendedPiTemplateOptionIds.add("https://w3id.org/np/RARW4MsFkHuwjycNElvEVtuMjpf4yWDL10-0C5l2MqqRQ");
×
656
        recommendedPiTemplateOptionIds.add("https://w3id.org/np/RA16U9Wo30ObhrK1NzH7EsmVRiRtvEuEA_Dfc-u8WkUCA");
×
657
        recommendedPiTemplateOptionIds.add("http://purl.org/np/RAdyqI6k07V5nAS82C6hvIDtNWk179EIV4DV-sLbOFKg4");
×
658
        recommendedPiTemplateOptionIds.add("https://w3id.org/np/RAjvEpLZUE7rMoa8q6mWSsN6utJDp-5FmgO47YGsbgw3w");
×
659
        recommendedPiTemplateOptionIds.add("http://purl.org/np/RAxuGRKID6yNg63V5Mf0ot2NjncOnodh-mkN3qT_1txGI");
×
660
        for (TemplateContext c : pubInfoContexts) {
×
661
            String s = c.getTemplate().getId();
×
662
            handledPiTemplates.put(s, true);
×
663
        }
×
664
        for (String s : recommendedPiTemplateOptionIds) {
×
665
            handledPiTemplates.put(s, true);
×
666
        }
×
667

668
        for (ApiResponseEntry entry : td.getPubInfoTemplates()) {
×
669
            String tid = entry.get("np");
×
670
            if (handledPiTemplates.containsKey(tid)) continue;
×
671
            piTemplateOptionIds.add(tid);
×
672
            handledPiTemplates.put(tid, true);
×
673
        }
×
674

675
        ChoiceProvider<String> piTemplateChoiceProvider = new ChoiceProvider<String>() {
×
676

677
            @Override
678
            public String getDisplayValue(String object) {
679
                if (object == null || object.isEmpty()) return "";
×
680
                Template t = td.getTemplate(object);
×
681
                if (t != null) return t.getLabel();
×
682
                return object;
×
683
            }
684

685
            @Override
686
            public String getIdValue(String object) {
687
                return object;
×
688
            }
689

690
            // Getting strange errors with Tomcat if this method is not overridden:
691
            @Override
692
            public void detach() {
693
            }
×
694

695
            @Override
696
            public void query(String term, int page, Response<String> response) {
697
                if (term == null) term = "";
×
698
                term = term.toLowerCase();
×
699
                if (!recommendedPiTemplateOptionIds.isEmpty()) {
×
700
                    response.add("—— recommended ——");
×
701
                    for (String s : recommendedPiTemplateOptionIds) {
×
702
                        boolean isAlreadyUsed = false;
×
703
                        for (TemplateContext c : pubInfoContexts) {
×
704
                            // TODO: make this more efficient/nicer
705
                            if (c.getTemplate().getId().equals(s)) {
×
706
                                isAlreadyUsed = true;
×
707
                                break;
×
708
                            }
709
                        }
×
710
                        if (isAlreadyUsed) continue;
×
711
                        if (s.toLowerCase().contains(term) || getDisplayValue(s).toLowerCase().contains(term)) {
×
712
                            response.add(s);
×
713
                        }
714
                    }
×
715
                }
716
                if (!piTemplateOptionIds.isEmpty()) {
×
717
                    response.add("—— others ——");
×
718
                    for (String s : piTemplateOptionIds) {
×
719
                        boolean isAlreadyUsed = false;
×
720
                        for (TemplateContext c : pubInfoContexts) {
×
721
                            // TODO: make this more efficient/nicer
722
                            if (c.getTemplate().getId().equals(s)) {
×
723
                                isAlreadyUsed = true;
×
724
                                break;
×
725
                            }
726
                        }
×
727
                        if (isAlreadyUsed) continue;
×
728
                        if (s.toLowerCase().contains(term) || getDisplayValue(s).toLowerCase().contains(term)) {
×
729
                            response.add(s);
×
730
                        }
731
                    }
×
732
                }
733
            }
×
734

735
            @Override
736
            public Collection<String> toChoices(Collection<String> ids) {
737
                return ids;
×
738
            }
739

740
        };
741
        final IModel<String> newPiTemplateModel = Model.of();
×
742
        Select2Choice<String> piTemplateChoice = new Select2Choice<String>("pitemplate", newPiTemplateModel, piTemplateChoiceProvider);
×
743
        piTemplateChoice.getSettings().setCloseOnSelect(true);
×
744
        piTemplateChoice.getSettings().setPlaceholder("add element...");
×
745
        piTemplateChoice.add(new AjaxFormComponentUpdatingBehavior("change") {
×
746

747
            @Override
748
            protected void onUpdate(AjaxRequestTarget target) {
749
                if (newPiTemplateModel.getObject().startsWith("——")) {
×
750
                    newPiTemplateModel.setObject(null);
×
751
                    refreshPubInfo(target);
×
752
                    return;
×
753
                }
754
                String id = newPiTemplateModel.getObject();
×
755
                TemplateContext c = new TemplateContext(ContextType.PUBINFO, id, "pi-statement", targetNamespace);
×
756
                c.initStatements();
×
757
                pubInfoContexts.add(c);
×
758
                newPiTemplateModel.setObject(null);
×
759
                refreshPubInfo(target);
×
760
                c.finalizeStatements();
×
761
            }
×
762

763
        });
764
        form.add(piTemplateChoice);
×
765
        refreshPubInfo(null);
×
766

767
        form.add(consentCheck);
×
768

769
        form.add(new Button("preview-button") {
×
770
            @Override
771
            public void onSubmit() {
772
                try {
773
                    Nanopub np = createNanopub();
×
774
                    TransformContext tc = new TransformContext(SignatureAlgorithm.RSA, NanodashSession.get().getKeyPair(), NanodashSession.get().getUserIri(), false, false, false);
×
775
                    Nanopub signedNp = SignNanopub.signAndTransform(np, tc);
×
776
                    String previewId = signedNp.getUri().stringValue();
×
777
                    NanodashSession.get().setPreviewNanopub(previewId,
×
778
                            new NanodashSession.PreviewNanopub(signedNp, pageParams, confirmPageClass, Boolean.TRUE.equals(consentCheck.getModelObject())));
×
779
                    throw new RestartResponseException(PreviewPage.class, new PageParameters().set("id", previewId));
×
780
                } catch (RestartResponseException ex) {
×
781
                    throw ex;
×
782
                } catch (Exception ex) {
×
783
                    logger.error("Preview failed: {}", ex.getMessage());
×
784
                    String message = ex.getClass().getName();
×
785
                    if (ex.getMessage() != null) {
×
786
                        message = ex.getMessage();
×
787
                    }
788
                    feedbackPanel.error(message);
×
789
                }
790
            }
×
791
        });
792

793
        add(form);
×
794

795
        feedbackPanel = new FeedbackPanel("feedback");
×
796
        feedbackPanel.setOutputMarkupId(true);
×
797
        add(feedbackPanel);
×
798
    }
×
799

800
    private void refreshProvenance(AjaxRequestTarget target) {
801
        if (target != null) {
×
802
            form.remove("prtemplatelink");
×
803
            form.remove("pr-statements");
×
804
            target.add(form);
×
805
            target.appendJavaScript("updateElements();");
×
806
        }
807
        form.add(new BookmarkablePageLink<Void>("prtemplatelink", ExplorePage.class, new PageParameters().set("id", provenanceContext.getTemplate().getId())));
×
808
        ListView<StatementItem> list = new ListView<StatementItem>("pr-statements", provenanceContext.getStatementItems()) {
×
809

810
            protected void populateItem(ListItem<StatementItem> item) {
811
                item.add(item.getModelObject());
×
812
            }
×
813

814
        };
815
        list.setOutputMarkupId(true);
×
816
        form.add(list);
×
817
    }
×
818

819
    private void refreshPubInfo(AjaxRequestTarget target) {
820
        ListView<TemplateContext> list = new ListView<TemplateContext>("pis", pubInfoContexts) {
×
821

822
            protected void populateItem(ListItem<TemplateContext> item) {
823
                final TemplateContext pic = item.getModelObject();
×
824
                item.add(new Label("pitemplatename", pic.getTemplate().getLabel()));
×
825
                item.add(new BookmarkablePageLink<Void>("pitemplatelink", ExplorePage.class, new PageParameters().set("id", pic.getTemplate().getId())));
×
826
                Label remove = new Label("piremove", "×");
×
827
                item.add(remove);
×
828
                remove.add(new AjaxEventBehavior("click") {
×
829

830
                    @Override
831
                    protected void onEvent(AjaxRequestTarget target) {
832
                        pubInfoContexts.remove(pic);
×
833
                        target.add(PublishForm.this);
×
834
                        target.appendJavaScript("updateElements();");
×
835
                    }
×
836

837
                });
838
                if (requiredPubInfoContexts.contains(pic)) remove.setVisible(false);
×
839
                item.add(new ListView<StatementItem>("pi-statements", pic.getStatementItems()) {
×
840

841
                    protected void populateItem(ListItem<StatementItem> item) {
842
                        item.add(item.getModelObject());
×
843
                    }
×
844

845
                });
846
            }
×
847

848
        };
849
        list.setOutputMarkupId(true);
×
850
        if (target == null) {
×
851
            form.add(list);
×
852
        } else {
853
            form.remove("pis");
×
854
            form.add(list);
×
855
            target.add(form);
×
856
            target.appendJavaScript("updateElements();");
×
857
        }
858
    }
×
859

860
    private TemplateContext createPubInfoContext(String piTemplateId) {
861
        TemplateContext c;
862
        if (pubInfoContextMap.containsKey(piTemplateId)) {
×
863
            c = pubInfoContextMap.get(piTemplateId);
×
864
        } else {
865
            c = new TemplateContext(ContextType.PUBINFO, piTemplateId, "pi-statement", targetNamespace);
×
866
            pubInfoContextMap.put(piTemplateId, c);
×
867
            pubInfoContexts.add(c);
×
868
        }
869
        return c;
×
870
    }
871

872
    private synchronized Nanopub createNanopub() throws MalformedNanopubException, NanopubAlreadyFinalizedException {
873
        assertionContext.getIntroducedIris().clear();
×
874
        NanopubCreator npCreator = new NanopubCreator(targetNamespace);
×
875
        npCreator.setAssertionUri(vf.createIRI(targetNamespace + "assertion"));
×
876
        assertionContext.propagateStatements(npCreator);
×
877
        provenanceContext.propagateStatements(npCreator);
×
878
        for (TemplateContext c : pubInfoContexts) {
×
879
            c.propagateStatements(npCreator);
×
880
        }
×
881
        for (IRI introducedIri : assertionContext.getIntroducedIris()) {
×
882
            npCreator.addPubinfoStatement(NPX.INTRODUCES, introducedIri);
×
883
        }
×
884
        for (IRI embeddedIri : assertionContext.getEmbeddedIris()) {
×
885
            npCreator.addPubinfoStatement(NPX.EMBEDS, embeddedIri);
×
886
        }
×
887
        npCreator.addNamespace("this", targetNamespace);
×
888
        npCreator.addNamespace("sub", targetNamespace + "/");
×
889
        npCreator.addTimestampNow();
×
890
        IRI templateUri = assertionContext.getTemplate().getNanopub().getUri();
×
891
        npCreator.addPubinfoStatement(NTEMPLATE.WAS_CREATED_FROM_TEMPLATE, templateUri);
×
892
        IRI prTemplateUri = provenanceContext.getTemplate().getNanopub().getUri();
×
893
        npCreator.addPubinfoStatement(NTEMPLATE.WAS_CREATED_FROM_PROVENANCE_TEMPLATE, prTemplateUri);
×
894
        for (TemplateContext c : pubInfoContexts) {
×
895
            IRI piTemplateUri = c.getTemplate().getNanopub().getUri();
×
896
            npCreator.addPubinfoStatement(NTEMPLATE.WAS_CREATED_FROM_PUBINFO_TEMPLATE, piTemplateUri);
×
897
        }
×
898
        String nanopubLabel = getNanopubLabel(npCreator);
×
899
        if (nanopubLabel != null) {
×
900
            npCreator.addPubinfoStatement(RDFS.LABEL, vf.createLiteral(nanopubLabel));
×
901
        }
902
        for (IRI type : assertionContext.getTemplate().getTargetNanopubTypes()) {
×
903
            npCreator.addPubinfoStatement(NPX.HAS_NANOPUB_TYPE, type);
×
904
        }
×
905
        IRI userIri = NanodashSession.get().getUserIri();
×
906
        if (User.getName(userIri) != null) {
×
907
            npCreator.addPubinfoStatement(userIri, FOAF.NAME, vf.createLiteral(User.getName(userIri)));
×
908
            npCreator.addNamespace("foaf", FOAF.NAMESPACE);
×
909
        }
910
        String websiteUrl = NanodashPreferences.get().getWebsiteUrl();
×
911
        if (websiteUrl != null) {
×
912
            npCreator.addPubinfoStatement(NPX.WAS_CREATED_AT, vf.createIRI(websiteUrl));
×
913
        }
914
        return npCreator.finalizeNanopub();
×
915
    }
916

917
    private String getNanopubLabel(NanopubCreator npCreator) {
918
        if (assertionContext.getTemplate().getNanopubLabelPattern() == null) return null;
×
919

920
        Map<IRI, String> labelMap = new HashMap<>();
×
921
        for (Statement st : npCreator.getCurrentPubinfoStatements()) {
×
922
            if (st.getPredicate().equals(RDFS.LABEL) && st.getObject() instanceof Literal objL) {
×
923
                labelMap.put((IRI) st.getSubject(), objL.stringValue());
×
924
            }
925
        }
×
926

927
        String nanopubLabel = assertionContext.getTemplate().getNanopubLabelPattern();
×
928
        while (nanopubLabel.matches(".*\\$\\{[_a-zA-Z0-9-]+\\}.*")) {
×
929
            String placeholderPostfix = nanopubLabel.replaceFirst("^.*\\$\\{([_a-zA-Z0-9-]+)\\}.*$", "$1");
×
930
            IRI placeholderIriHash = vf.createIRI(assertionContext.getTemplateId() + "#" + placeholderPostfix);
×
931
            IRI placeholderIriSlash = vf.createIRI(assertionContext.getTemplateId() + "/" + placeholderPostfix);
×
932
            IRI placeholderIri;
933
            String placeholderValue = "";
×
934
            if (assertionContext.getComponentModels().get(placeholderIriSlash) != null) {
×
935
                placeholderIri = placeholderIriSlash;
×
936
            } else {
937
                placeholderIri = placeholderIriHash;
×
938
            }
939
            IModel<String> m = (IModel<String>) assertionContext.getComponentModels().get(placeholderIri);
×
940
            if (m != null) placeholderValue = m.orElse("").getObject();
×
941
            if (placeholderValue == null) placeholderValue = "";
×
942
            String placeholderLabel = placeholderValue;
×
943
            if (assertionContext.getTemplate().isUriPlaceholder(placeholderIri)) {
×
944
                try {
945
                    // TODO Fix this. It doesn't work for placeholders with auto-encode placeholders, etc.
946
                    //      Not sure we need labels for these, but this code should be improved anyway.
947
                    String prefix = assertionContext.getTemplate().getPrefix(placeholderIri);
×
948
                    if (prefix != null) placeholderValue = prefix + placeholderValue;
×
949
                    IRI placeholderValueIri = vf.createIRI(placeholderValue);
×
950
                    String l = assertionContext.getTemplate().getLabel(placeholderValueIri);
×
951
                    if (labelMap.containsKey(placeholderValueIri)) {
×
952
                        l = labelMap.get(placeholderValueIri);
×
953
                    }
954
                    if (l == null) l = GuidedChoiceItem.getLabel(placeholderValue);
×
955
                    if (assertionContext.getTemplate().isAgentPlaceholder(placeholderIri) && !placeholderValue.isEmpty()) {
×
956
                        l = User.getName(vf.createIRI(placeholderValue));
×
957
                    }
958
                    if (l != null && !l.isEmpty()) {
×
959
                        placeholderLabel = l.replaceFirst(" - .*$", "");
×
960
                    } else {
961
                        placeholderLabel = Utils.getShortNameFromURI(placeholderValueIri);
×
962
                    }
963
                } catch (Exception ex) {
×
964
                    logger.error("Nanopub label placeholder IRI error: {}", ex.getMessage());
×
965
                }
×
966
            }
967
            placeholderLabel = placeholderLabel.replaceAll("\\s+", " ");
×
968
            if (placeholderLabel.length() > 100) placeholderLabel = placeholderLabel.substring(0, 97) + "...";
×
969
            nanopubLabel = Strings.CS.replace(nanopubLabel, "${" + placeholderPostfix + "}", placeholderLabel);
×
970
        }
×
971
        return nanopubLabel;
×
972
    }
973

974
    private NanodashPage getConfirmPage(Nanopub signedNp, PageParameters pageParams) {
975
        try {
976
            return (NanodashPage) confirmPageClass.getConstructor(Nanopub.class, PageParameters.class).newInstance(signedNp, pageParams);
×
977
        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException |
×
978
                 InvocationTargetException | NoSuchMethodException | SecurityException ex) {
979
            logger.error("Could not create instance of confirmation page: {}", ex.getMessage());
×
980
        }
981
        return null;
×
982
    }
983

984
    /**
985
     * Returns a hint whether the form is stateless or not.
986
     *
987
     * @return false if the form is stateful, true if it is stateless.
988
     */
989
    // This is supposed to solve the problem that sometimes (but only sometimes) form content is reset
990
    // if the user browses other pages in parallel:
991
    protected boolean getStatelessHint() {
992
        return false;
×
993
    }
994

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