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

knowledgepixels / nanodash / 18155160356

01 Oct 2025 07:42AM UTC coverage: 13.788% (-0.03%) from 13.817%
18155160356

push

github

ashleycaselli
docs: add missing or update Javadoc annotations

445 of 4084 branches covered (10.9%)

Branch coverage included in aggregate %.

1155 of 7520 relevant lines covered (15.36%)

0.69 hits per line

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

0.3
src/main/java/com/knowledgepixels/nanodash/template/TemplateContext.java
1
package com.knowledgepixels.nanodash.template;
2

3
import com.knowledgepixels.nanodash.NanodashSession;
4
import com.knowledgepixels.nanodash.Utils;
5
import com.knowledgepixels.nanodash.component.PublishForm.FillMode;
6
import com.knowledgepixels.nanodash.component.StatementItem;
7
import org.apache.wicket.Component;
8
import org.apache.wicket.model.IModel;
9
import org.apache.wicket.model.Model;
10
import org.eclipse.rdf4j.model.IRI;
11
import org.eclipse.rdf4j.model.Statement;
12
import org.eclipse.rdf4j.model.Value;
13
import org.eclipse.rdf4j.model.ValueFactory;
14
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
15
import org.eclipse.rdf4j.model.vocabulary.RDFS;
16
import org.nanopub.*;
17
import org.nanopub.vocabulary.NTEMPLATE;
18

19
import java.io.Serializable;
20
import java.util.*;
21

22
/**
23
 * Context for a template, containing all necessary information to fill.
24
 */
25
public class TemplateContext implements Serializable {
26

27
    private static ValueFactory vf = SimpleValueFactory.getInstance();
3✔
28

29
    private final ContextType contextType;
30
    private final Template template;
31
    private final String componentId;
32
    private final Map<String, String> params = new HashMap<>();
×
33
    private List<Component> components = new ArrayList<>();
×
34
    private Map<IRI, IModel<String>> componentModels = new HashMap<>();
×
35
    private Set<IRI> introducedIris = new HashSet<>();
×
36
    private Set<IRI> embeddedIris = new HashSet<>();
×
37
    private List<StatementItem> statementItems;
38
    private Set<IRI> iriSet = new HashSet<>();
×
39
    private Map<IRI, StatementItem> narrowScopeMap = new HashMap<>();
×
40
    private String targetNamespace = Template.DEFAULT_TARGET_NAMESPACE;
×
41
    private Nanopub existingNanopub;
42
    private Map<IRI, String> labels;
43
    private FillMode fillMode = null;
×
44

45
    /**
46
     * Constructor for creating a new template context for filling a template.
47
     *
48
     * @param contextType     the type of context
49
     * @param templateId      the ID of the template to fill
50
     * @param componentId     the ID of the component that will use this context
51
     * @param targetNamespace the target namespace for the template, can be null to use the default namespace
52
     */
53
    public TemplateContext(ContextType contextType, String templateId, String componentId, String targetNamespace) {
54
        this(contextType, templateId, componentId, targetNamespace, null);
×
55
    }
×
56

57
    /**
58
     * Constructor for creating a new template context for filling a template.
59
     *
60
     * @param contextType     the type of context
61
     * @param templateId      the ID of the template to fill
62
     * @param componentId     the ID of the component that will use this context
63
     * @param existingNanopub an existing nanopub to fill, can be null if creating a new nanopub
64
     */
65
    public TemplateContext(ContextType contextType, String templateId, String componentId, Nanopub existingNanopub) {
66
        this(contextType, templateId, componentId, null, existingNanopub);
×
67
    }
×
68

69
    private TemplateContext(ContextType contextType, String templateId, String componentId, String targetNamespace, Nanopub existingNanopub) {
×
70
        this.contextType = contextType;
×
71
        // TODO: check whether template is of correct type:
72
        this.template = TemplateData.get().getTemplate(templateId);
×
73
        this.componentId = componentId;
×
74
        if (targetNamespace != null) {
×
75
            this.targetNamespace = targetNamespace;
×
76
        }
77
        this.existingNanopub = existingNanopub;
×
78
        if (existingNanopub == null && NanodashSession.get().getUserIri() != null) {
×
79
            componentModels.put(NTEMPLATE.CREATOR_PLACEHOLDER, Model.of(NanodashSession.get().getUserIri().stringValue()));
×
80
        }
81
    }
×
82

83
    /**
84
     * Initializes the statements for this context.
85
     */
86
    public void initStatements() {
87
        if (statementItems != null) return;
×
88
        statementItems = new ArrayList<>();
×
89
        for (IRI st : template.getStatementIris()) {
×
90
            StatementItem si = new StatementItem(componentId, st, this);
×
91
            statementItems.add(si);
×
92
            for (IRI i : si.getIriSet()) {
×
93
                if (iriSet.contains(i)) {
×
94
                    narrowScopeMap.remove(i);
×
95
                } else {
96
                    iriSet.add(i);
×
97
                    narrowScopeMap.put(i, si);
×
98
                }
99
            }
×
100
        }
×
101
    }
×
102

103
    /**
104
     * Finalizes the statements by processing all parameters and setting the repetition counts.
105
     */
106
    public void finalizeStatements() {
107
        Map<StatementItem, Integer> finalRepetitionCount = new HashMap<>();
×
108
        for (IRI ni : narrowScopeMap.keySet()) {
×
109
            // TODO: Move all occurrences of this to utility function:
110
            String postfix = Utils.getUriPostfix(ni);
×
111
            StatementItem si = narrowScopeMap.get(ni);
×
112
            int i = si.getRepetitionCount();
×
113
            while (true) {
114
                String p = postfix + "__" + i;
×
115
                if (hasParam(p)) {
×
116
                    si.addRepetitionGroup();
×
117
                } else {
118
                    break;
119
                }
120
                i++;
×
121
            }
×
122
            i = 1;
×
123
            int corr = 0;
×
124
            if (si.isEmpty()) corr = 1;
×
125
            while (true) {
126
                String p = postfix + "__." + i;
×
127
                if (hasParam(p)) {
×
128
                    int absPos = si.getRepetitionCount() + i - 1 - corr;
×
129
                    String param = postfix + "__" + absPos;
×
130
                    if (i - corr == 0) param = postfix;
×
131
                    setParam(param, getParam(p));
×
132
                    finalRepetitionCount.put(si, i - corr);
×
133
                } else {
134
                    break;
135
                }
136
                i++;
×
137
            }
×
138
        }
×
139
        for (StatementItem si : finalRepetitionCount.keySet()) {
×
140
            for (int i = 0; i < finalRepetitionCount.get(si); i++) {
×
141
                si.addRepetitionGroup();
×
142
            }
143
        }
×
144
        for (StatementItem si : statementItems) {
×
145
            si.finalizeValues();
×
146
        }
×
147
    }
×
148

149
    /**
150
     * Sets the fill mode for this context.
151
     *
152
     * @param fillMode the fill mode to set
153
     */
154
    public void setFillMode(FillMode fillMode) {
155
        this.fillMode = fillMode;
×
156
    }
×
157

158
    /**
159
     * Gets the fill mode for this context.
160
     *
161
     * @return the fill mode, or null if not set
162
     */
163
    public FillMode getFillMode() {
164
        return fillMode;
×
165
    }
166

167
    /**
168
     * Returns the type of context.
169
     *
170
     * @return the context type
171
     */
172
    public ContextType getType() {
173
        return contextType;
×
174
    }
175

176
    /**
177
     * Returns the template associated with this context.
178
     *
179
     * @return the template
180
     */
181
    public Template getTemplate() {
182
        return template;
×
183
    }
184

185
    /**
186
     * Returns the ID of the template associated with this context.
187
     *
188
     * @return the template ID
189
     */
190
    public String getTemplateId() {
191
        return template.getId();
×
192
    }
193

194
    /**
195
     * Sets a parameter for this context.
196
     *
197
     * @param name  the name of the parameter
198
     * @param value the value of the parameter
199
     */
200
    public void setParam(String name, String value) {
201
        params.put(name, value);
×
202
    }
×
203

204
    /**
205
     * Gets a parameter value by its name.
206
     *
207
     * @param name the name of the parameter
208
     * @return the value of the parameter, or null if not set
209
     */
210
    public String getParam(String name) {
211
        return params.get(name);
×
212
    }
213

214
    /**
215
     * Checks if a parameter with the given name exists.
216
     *
217
     * @param name the name of the parameter
218
     * @return true if the parameter exists, false otherwise
219
     */
220
    public boolean hasParam(String name) {
221
        return params.containsKey(name);
×
222
    }
223

224
    /**
225
     * Returns the components associated with this context.
226
     *
227
     * @return a list of components
228
     */
229
    public List<Component> getComponents() {
230
        return components;
×
231
    }
232

233
    /**
234
     * Returns the component models associated with this context.
235
     *
236
     * @return a map of IRI to model of strings
237
     */
238
    public Map<IRI, IModel<String>> getComponentModels() {
239
        return componentModels;
×
240
    }
241

242
    /**
243
     * Returns the introduced IRIs in this context.
244
     *
245
     * @return a set of introduced IRIs
246
     */
247
    public Set<IRI> getIntroducedIris() {
248
        return introducedIris;
×
249
    }
250

251
    /**
252
     * Returns the embedded IRIs in this context.
253
     *
254
     * @return a set of embedded IRIs
255
     */
256
    public Set<IRI> getEmbeddedIris() {
257
        return embeddedIris;
×
258
    }
259

260
    /**
261
     * Processes an IRI by applying the template's processing rules.
262
     *
263
     * @param iri the IRI to process
264
     * @return the processed IRI, or null if the processing results in no value
265
     */
266
    public IRI processIri(IRI iri) {
267
        Value v = processValue(iri);
×
268
        if (v == null) return null;
×
269
        if (v instanceof IRI) return (IRI) v;
×
270
        return iri;
×
271
    }
272

273
    /**
274
     * Processes a Value according to the template's rules.
275
     *
276
     * @param value the Value to process
277
     * @return the processed Value, or the original Value if no processing is applicable
278
     */
279
    public Value processValue(Value value) {
280
        if (!(value instanceof IRI)) return value;
×
281
        IRI iri = (IRI) value;
×
282
        if (iri.equals(NTEMPLATE.CREATOR_PLACEHOLDER)) {
×
283
            iri = NanodashSession.get().getUserIri();
×
284
        }
285
        if (iri.equals(NTEMPLATE.ASSERTION_PLACEHOLDER)) {
×
286
            iri = vf.createIRI(targetNamespace + "assertion");
×
287
        } else if (iri.equals(NTEMPLATE.NANOPUB_PLACEHOLDER)) {
×
288
            iri = vf.createIRI(targetNamespace);
×
289
        }
290
        // TODO: Move this code below to the respective placeholder classes:
291
        IModel<String> tf = componentModels.get(iri);
×
292
        Value processedValue = null;
×
293
        if (template.isRestrictedChoicePlaceholder(iri)) {
×
294
            if (tf != null && tf.getObject() != null && !tf.getObject().isEmpty()) {
×
295
                String prefix = template.getPrefix(iri);
×
296
                if (prefix == null) prefix = "";
×
297
                if (template.isLocalResource(iri)) prefix = targetNamespace;
×
298
                if (tf.getObject().matches("https?://.+")) prefix = "";
×
299
                String v = prefix + tf.getObject();
×
300
                if (v.matches("[^:# ]+")) v = targetNamespace + v;
×
301
                if (v.matches("https?://.*")) {
×
302
                    processedValue = vf.createIRI(v);
×
303
                } else {
304
                    processedValue = vf.createLiteral(tf.getObject());
×
305
                }
306
            }
×
307
        } else if (template.isUriPlaceholder(iri)) {
×
308
            if (tf != null && tf.getObject() != null && !tf.getObject().isEmpty()) {
×
309
                String prefix = template.getPrefix(iri);
×
310
                if (prefix == null) prefix = "";
×
311
                if (template.isLocalResource(iri)) prefix = targetNamespace;
×
312
                String v;
313
                if (template.isAutoEscapePlaceholder(iri)) {
×
314
                    v = prefix + Utils.urlEncode(tf.getObject());
×
315
                } else {
316
                    if (tf.getObject().matches("https?://.+")) prefix = "";
×
317
                    v = prefix + tf.getObject();
×
318
                }
319
                if (v.matches("[^:# ]+")) v = targetNamespace + v;
×
320
                processedValue = vf.createIRI(v);
×
321
            }
×
322
        } else if (template.isLocalResource(iri)) {
×
323
            String prefix = Utils.getUriPrefix(iri);
×
324
            processedValue = vf.createIRI(iri.stringValue().replace(prefix, targetNamespace));
×
325
        } else if (template.isLiteralPlaceholder(iri)) {
×
326
            IRI datatype = template.getDatatype(iri);
×
327
            String languagetag = template.getLanguageTag(iri);
×
328
            if (tf != null && tf.getObject() != null && !tf.getObject().isEmpty()) {
×
329
                if (datatype != null) {
×
330
                    processedValue = vf.createLiteral(tf.getObject(), datatype);
×
331
                } else if (languagetag != null) {
×
332
                    processedValue = vf.createLiteral(tf.getObject(), languagetag);
×
333
                } else {
334
                    processedValue = vf.createLiteral(tf.getObject());
×
335
                }
336
            }
337

338
        } else if (template.isValuePlaceholder(iri)) {
×
339
            if (tf != null && tf.getObject() != null && !tf.getObject().isEmpty()) {
×
340
                if (Utils.isValidLiteralSerialization(tf.getObject())) {
×
341
                    processedValue = Utils.getParsedLiteral(tf.getObject());
×
342
                } else {
343
                    String v = tf.getObject();
×
344
                    if (v.matches("[^:# ]+")) v = targetNamespace + v;
×
345
                    processedValue = vf.createIRI(v);
×
346
                }
×
347
            }
348
        } else if (template.isSequenceElementPlaceholder(iri)) {
×
349
            if (tf != null && tf.getObject() != null && !tf.getObject().isEmpty()) {
×
350
                processedValue = vf.createIRI(tf.getObject());
×
351
            }
352
        } else {
353
            processedValue = iri;
×
354
        }
355
        if (processedValue instanceof IRI pvIri && template.isIntroducedResource(iri)) {
×
356
            introducedIris.add(pvIri);
×
357
        }
358
        if (processedValue instanceof IRI pvIri && template.isEmbeddedResource(iri)) {
×
359
            embeddedIris.add(pvIri);
×
360
        }
361
        return processedValue;
×
362
    }
363

364
    /**
365
     * Returns the statement items associated with this context.
366
     *
367
     * @return a list of StatementItem objects
368
     */
369
    public List<StatementItem> getStatementItems() {
370
        return statementItems;
×
371
    }
372

373
    /**
374
     * Propagates the statements from this context to a NanopubCreator.
375
     *
376
     * @param npCreator the NanopubCreator to which the statements will be added
377
     * @throws org.nanopub.MalformedNanopubException        if there is an error in the nanopub structure
378
     * @throws org.nanopub.NanopubAlreadyFinalizedException if the nanopub has already been finalized
379
     */
380
    public void propagateStatements(NanopubCreator npCreator) throws MalformedNanopubException, NanopubAlreadyFinalizedException {
381
        if (template.getNanopub() instanceof NanopubWithNs) {
×
382
            NanopubWithNs np = (NanopubWithNs) template.getNanopub();
×
383
            for (String p : np.getNsPrefixes()) {
×
384
                npCreator.addNamespace(p, np.getNamespace(p));
×
385
            }
×
386
        }
387
        for (StatementItem si : statementItems) {
×
388
            si.addTriplesTo(npCreator);
×
389
        }
×
390
    }
×
391

392
    /**
393
     * Checks if the context has a narrow scope for the given IRI.
394
     *
395
     * @param iri the IRI to check
396
     * @return true if there is a narrow scope for the IRI, false otherwise
397
     */
398
    public boolean hasNarrowScope(IRI iri) {
399
        return narrowScopeMap.containsKey(iri);
×
400
    }
401

402
    /**
403
     * Checks if any of the statement items in this context will match any triple.
404
     *
405
     * @return true if any statement item will match any triple, false otherwise
406
     */
407
    public boolean willMatchAnyTriple() {
408
        initStatements();
×
409
        for (StatementItem si : statementItems) {
×
410
            if (si.willMatchAnyTriple()) return true;
×
411
        }
×
412
        return false;
×
413
    }
414

415
    /**
416
     * Fills the context with statements, processing each StatementItem.
417
     *
418
     * @param statements the list of statements to fill
419
     * @throws com.knowledgepixels.nanodash.template.UnificationException if there is an error during unification of statements
420
     */
421
    public void fill(List<Statement> statements) throws UnificationException {
422
        for (StatementItem si : statementItems) {
×
423
            si.fill(statements);
×
424
        }
×
425
        for (StatementItem si : statementItems) {
×
426
            si.fillFinished();
×
427
        }
×
428
    }
×
429

430
    /**
431
     * Returns the existing Nanopub associated with this context, if any.
432
     *
433
     * @return the existing Nanopub, or null if this context is for a new Nanopub
434
     */
435
    public Nanopub getExistingNanopub() {
436
        return existingNanopub;
×
437
    }
438

439
    /**
440
     * Checks if this context is read-only.
441
     *
442
     * @return true if the context is read-only, false otherwise
443
     */
444
    public boolean isReadOnly() {
445
        return existingNanopub != null;
×
446
    }
447

448
    /**
449
     * Returns the label for a given IRI, if available.
450
     *
451
     * @param iri the IRI for which to get the label
452
     * @return the label as a String, or null if no label is found
453
     */
454
    public String getLabel(IRI iri) {
455
        if (existingNanopub == null) return null;
×
456
        if (labels == null) {
×
457
            labels = new HashMap<>();
×
458
            for (Statement st : existingNanopub.getPubinfo()) {
×
459
                if (st.getPredicate().equals(NTEMPLATE.HAS_LABEL_FROM_API) || st.getPredicate().equals(RDFS.LABEL)) {
×
460
                    String label = st.getObject().stringValue();
×
461
                    labels.put((IRI) st.getSubject(), label);
×
462
                }
463
            }
×
464
        }
465
        return labels.get(iri);
×
466
    }
467

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