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

knowledgepixels / nanodash / 17235948541

26 Aug 2025 10:54AM UTC coverage: 12.455% (-0.02%) from 12.474%
17235948541

push

github

tkuhn
Use Literals.normalizeLanguageTag for normalizing literal language tags

332 of 3800 branches covered (8.74%)

Branch coverage included in aggregate %.

988 of 6798 relevant lines covered (14.53%)

0.64 hits per line

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

24.91
src/main/java/com/knowledgepixels/nanodash/template/Template.java
1
package com.knowledgepixels.nanodash.template;
2

3
import java.io.Serializable;
4
import java.util.ArrayList;
5
import java.util.Comparator;
6
import java.util.HashMap;
7
import java.util.List;
8
import java.util.Map;
9

10
import org.eclipse.rdf4j.common.exception.RDF4JException;
11
import org.eclipse.rdf4j.model.IRI;
12
import org.eclipse.rdf4j.model.Literal;
13
import org.eclipse.rdf4j.model.Statement;
14
import org.eclipse.rdf4j.model.Value;
15
import org.eclipse.rdf4j.model.ValueFactory;
16
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
17
import org.eclipse.rdf4j.model.util.Literals;
18
import org.eclipse.rdf4j.model.vocabulary.DCTERMS;
19
import org.eclipse.rdf4j.model.vocabulary.RDF;
20
import org.eclipse.rdf4j.model.vocabulary.RDFS;
21
import org.eclipse.rdf4j.model.vocabulary.SHACL;
22
import org.nanopub.Nanopub;
23
import org.nanopub.NanopubUtils;
24

25
import com.knowledgepixels.nanodash.LookupApis;
26
import com.knowledgepixels.nanodash.Utils;
27

28
import net.trustyuri.TrustyUriUtils;
29

30
/**
31
 * Represents a template for creating nanopublications.
32
 */
33
public class Template implements Serializable {
34

35
    private static final long serialVersionUID = 1L;
36

37
    private static ValueFactory vf = SimpleValueFactory.getInstance();
2✔
38
    /**
39
     * Represents the class for assertion templates.
40
     */
41
    public static final IRI ASSERTION_TEMPLATE_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/AssertionTemplate");
4✔
42

43
    /**
44
     * Represents the class for provenance templates.
45
     */
46
    public static final IRI PROVENANCE_TEMPLATE_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/ProvenanceTemplate");
4✔
47

48
    /**
49
     * Represents the class for publication information templates.
50
     */
51
    public static final IRI PUBINFO_TEMPLATE_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/PubinfoTemplate");
4✔
52

53
    /**
54
     * Represents the class for unlisted templates.
55
     */
56
    public static final IRI UNLISTED_TEMPLATE_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/UnlistedTemplate");
4✔
57

58
    /**
59
     * Predicate indicating a statement in the template.
60
     */
61
    public static final IRI HAS_STATEMENT_PREDICATE = vf.createIRI("https://w3id.org/np/o/ntemplate/hasStatement");
4✔
62

63
    /**
64
     * Represents the class for local resources.
65
     */
66
    public static final IRI LOCAL_RESOURCE_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/LocalResource");
4✔
67

68
    /**
69
     * Represents the class for introduced resources.
70
     */
71
    public static final IRI INTRODUCED_RESOURCE_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/IntroducedResource");
4✔
72

73
    /**
74
     * Represents the class for embedded resources.
75
     */
76
    public static final IRI EMBEDDED_RESOURCE_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/EmbeddedResource");
4✔
77

78
    /**
79
     * Represents the class for value placeholders.
80
     */
81
    public static final IRI VALUE_PLACEHOLDER_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/ValuePlaceholder");
4✔
82

83
    /**
84
     * Represents the class for URI placeholders.
85
     */
86
    public static final IRI URI_PLACEHOLDER_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/UriPlaceholder");
4✔
87

88
    /**
89
     * Represents the class for auto-escaped URI placeholders.
90
     */
91
    public static final IRI AUTO_ESCAPE_URI_PLACEHOLDER_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/AutoEscapeUriPlaceholder");
4✔
92

93
    /**
94
     * Represents the class for external URI placeholders.
95
     */
96
    public static final IRI EXTERNAL_URI_PLACEHOLDER_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/ExternalUriPlaceholder");
4✔
97

98
    /**
99
     * Represents the class for trusty URI placeholders.
100
     */
101
    public static final IRI TRUSTY_URI_PLACEHOLDER_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/TrustyUriPlaceholder");
4✔
102

103
    /**
104
     * Represents the class for literal placeholders.
105
     */
106
    public static final IRI LITERAL_PLACEHOLDER_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/LiteralPlaceholder");
4✔
107

108
    /**
109
     * Represents the class for long literal placeholders.
110
     */
111
    public static final IRI LONG_LITERAL_PLACEHOLDER_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/LongLiteralPlaceholder");
4✔
112

113
    /**
114
     * Represents the class for restricted choice placeholders.
115
     */
116
    public static final IRI RESTRICTED_CHOICE_PLACEHOLDER_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/RestrictedChoicePlaceholder");
4✔
117

118
    /**
119
     * Represents the class for guided choice placeholders.
120
     */
121
    public static final IRI GUIDED_CHOICE_PLACEHOLDER_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/GuidedChoicePlaceholder");
4✔
122

123
    /**
124
     * Represents the class for agent placeholders.
125
     */
126
    public static final IRI AGENT_PLACEHOLDER_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/AgentPlaceholder");
4✔
127

128
    /**
129
     * Represents the placeholder for the creator.
130
     */
131
    public static final IRI CREATOR_PLACEHOLDER = vf.createIRI("https://w3id.org/np/o/ntemplate/CREATOR");
4✔
132

133
    /**
134
     * Represents the placeholder for assertions.
135
     */
136
    public static final IRI ASSERTION_PLACEHOLDER = vf.createIRI("https://w3id.org/np/o/ntemplate/ASSERTION");
4✔
137

138
    /**
139
     * Represents the placeholder for nanopublications.
140
     */
141
    public static final IRI NANOPUB_PLACEHOLDER = vf.createIRI("https://w3id.org/np/o/ntemplate/NANOPUB");
4✔
142

143
    /**
144
     * Predicate indicating creation from a template.
145
     */
146
    public static final IRI WAS_CREATED_FROM_TEMPLATE_PREDICATE = vf.createIRI("https://w3id.org/np/o/ntemplate/wasCreatedFromTemplate");
4✔
147

148
    /**
149
     * Predicate indicating creation from a provenance template.
150
     */
151
    public static final IRI WAS_CREATED_FROM_PROVENANCE_TEMPLATE_PREDICATE = vf.createIRI("https://w3id.org/np/o/ntemplate/wasCreatedFromProvenanceTemplate");
4✔
152

153
    /**
154
     * Predicate indicating creation from a pubinfo template.
155
     */
156
    public static final IRI WAS_CREATED_FROM_PUBINFO_TEMPLATE_PREDICATE = vf.createIRI("https://w3id.org/np/o/ntemplate/wasCreatedFromPubinfoTemplate");
4✔
157

158
    /**
159
     * Predicate indicating the order of statements.
160
     */
161
    public static final IRI STATEMENT_ORDER_PREDICATE = vf.createIRI("https://w3id.org/np/o/ntemplate/statementOrder");
4✔
162

163
    /**
164
     * Predicate indicating possible values.
165
     */
166
    public static final IRI POSSIBLE_VALUE_PREDICATE = vf.createIRI("https://w3id.org/np/o/ntemplate/possibleValue");
4✔
167

168
    /**
169
     * Predicate indicating the source of possible values.
170
     */
171
    public static final IRI POSSIBLE_VALUES_FROM_PREDICATE = vf.createIRI("https://w3id.org/np/o/ntemplate/possibleValuesFrom");
4✔
172

173
    /**
174
     * Predicate indicating possible values from an API.
175
     */
176
    public static final IRI POSSIBLE_VALUES_FROM_API_PREDICATE = vf.createIRI("https://w3id.org/np/o/ntemplate/possibleValuesFromApi");
4✔
177

178
    /**
179
     * Predicate indicating a datatype for a literal placeholder.
180
     */
181
    public static final IRI HAS_DATATYPE_PREDICATE = vf.createIRI("https://w3id.org/np/o/ntemplate/hasDatatype");
4✔
182

183
    /**
184
     * Predicate indicating the language attribute for a literal placeholder.
185
     */
186
    public static final IRI HAS_LANGUATE_ATTRIBUTE_PREDICATE = vf.createIRI("https://w3id.org/np/o/ntemplate/hasLanguageAttribute");
4✔
187

188
    /**
189
     * Predicate indicating a prefix.
190
     */
191
    public static final IRI HAS_PREFIX_PREDICATE = vf.createIRI("https://w3id.org/np/o/ntemplate/hasPrefix");
4✔
192

193
    /**
194
     * Predicate indicating a regular expression.
195
     */
196
    public static final IRI HAS_REGEX_PREDICATE = vf.createIRI("https://w3id.org/np/o/ntemplate/hasRegex");
4✔
197

198
    /**
199
     * Predicate indicating a prefix label.
200
     */
201
    public static final IRI HAS_PREFIX_LABEL_PREDICATE = vf.createIRI("https://w3id.org/np/o/ntemplate/hasPrefixLabel");
4✔
202

203
    /**
204
     * Represents the class for optional statements.
205
     */
206
    public static final IRI OPTIONAL_STATEMENT_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/OptionalStatement");
4✔
207

208
    /**
209
     * Represents the class for grouped statements.
210
     */
211
    public static final IRI GROUPED_STATEMENT_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/GroupedStatement");
4✔
212

213
    /**
214
     * Represents the class for repeatable statements.
215
     */
216
    public static final IRI REPEATABLE_STATEMENT_CLASS = vf.createIRI("https://w3id.org/np/o/ntemplate/RepeatableStatement");
4✔
217

218
    /**
219
     * Predicate indicating default provenance.
220
     */
221
    public static final IRI HAS_DEFAULT_PROVENANCE_PREDICATE = vf.createIRI("https://w3id.org/np/o/ntemplate/hasDefaultProvenance");
4✔
222

223
    /**
224
     * Predicate indicating required pubinfo elements.
225
     */
226
    public static final IRI HAS_REQUIRED_PUBINFO_ELEMENT_PREDICATE = vf.createIRI("https://w3id.org/np/o/ntemplate/hasRequiredPubinfoElement");
4✔
227

228
    /**
229
     * Predicate indicating a tag.
230
     */
231
    public static final IRI HAS_TAG = vf.createIRI("https://w3id.org/np/o/ntemplate/hasTag");
4✔
232

233
    /**
234
     * Predicate indicating a label from an API.
235
     */
236
    public static final IRI HAS_LABEL_FROM_API = vf.createIRI("https://w3id.org/np/o/ntemplate/hasLabelFromApi");
4✔
237

238
    /**
239
     * Predicate indicating a default value.
240
     */
241
    public static final IRI HAS_DEFAULT_VALUE = vf.createIRI("https://w3id.org/np/o/ntemplate/hasDefaultValue");
4✔
242

243
    /**
244
     * Predicate indicating a target namespace.
245
     */
246
    public static final IRI HAS_TARGET_NAMESPACE = vf.createIRI("https://w3id.org/np/o/ntemplate/hasTargetNamespace");
4✔
247

248
    /**
249
     * Predicate indicating a nanopublication label pattern.
250
     */
251
    public static final IRI HAS_NANOPUB_LABEL_PATTERN = vf.createIRI("https://w3id.org/np/o/ntemplate/hasNanopubLabelPattern");
4✔
252

253
    /**
254
     * Predicate indicating a target nanopublication type.
255
     */
256
    public static final IRI HAS_TARGET_NANOPUB_TYPE = vf.createIRI("https://w3id.org/np/o/ntemplate/hasTargetNanopubType");
4✔
257

258
    /**
259
     * Represents the placeholder for sequence elements.
260
     */
261
    public static final IRI SEQUENCE_ELEMENT_PLACEHOLDER = vf.createIRI("https://w3id.org/np/o/ntemplate/SequenceElementPlaceholder");
5✔
262

263
    /**
264
     * Default target namespace for templates.
265
     */
266
    public static final String DEFAULT_TARGET_NAMESPACE = "https://w3id.org/np/";
267

268
    private Nanopub nanopub;
269
    private String label;
270
    private String description;
271

272
    // TODO: Make all these maps more generic and the code simpler:
273
    private IRI templateIri;
274
    private Map<IRI, List<IRI>> typeMap = new HashMap<>();
5✔
275
    private Map<IRI, List<Value>> possibleValueMap = new HashMap<>();
5✔
276
    private Map<IRI, List<IRI>> possibleValuesToLoadMap = new HashMap<>();
5✔
277
    private Map<IRI, List<String>> apiMap = new HashMap<>();
5✔
278
    private Map<IRI, String> labelMap = new HashMap<>();
5✔
279
    private Map<IRI, IRI> datatypeMap = new HashMap<>();
5✔
280
    private Map<IRI, String> languageAttributeMap = new HashMap<>();
5✔
281
    private Map<IRI, String> prefixMap = new HashMap<>();
5✔
282
    private Map<IRI, String> prefixLabelMap = new HashMap<>();
5✔
283
    private Map<IRI, String> regexMap = new HashMap<>();
5✔
284
    private Map<IRI, List<IRI>> statementMap = new HashMap<>();
5✔
285
    private Map<IRI, IRI> statementSubjects = new HashMap<>();
5✔
286
    private Map<IRI, IRI> statementPredicates = new HashMap<>();
5✔
287
    private Map<IRI, Value> statementObjects = new HashMap<>();
5✔
288
    private Map<IRI, Integer> statementOrder = new HashMap<>();
5✔
289
    private IRI defaultProvenance;
290
    private List<IRI> requiredPubinfoElements = new ArrayList<>();
5✔
291
    private String tag = null;
3✔
292
    private Map<IRI, Value> defaultValues = new HashMap<>();
5✔
293
    private String targetNamespace = null;
3✔
294
    private String nanopubLabelPattern;
295
    private List<IRI> targetNanopubTypes = new ArrayList<>();
5✔
296

297
    /**
298
     * Creates a Template object from a template id.
299
     *
300
     * @param templateId the id of the template, which is the URI of a nanopublication that contains the template definition.
301
     * @throws RDF4JException             if there is an error retrieving the nanopublication.
302
     * @throws MalformedTemplateException if the template is malformed or not a valid nanopub template.
303
     */
304
    Template(String templateId) throws RDF4JException, MalformedTemplateException {
2✔
305
        nanopub = Utils.getNanopub(templateId);
4✔
306
        processTemplate(nanopub);
4✔
307
    }
1✔
308

309
    /**
310
     * Checks if the template is unlisted.
311
     *
312
     * @return true if the template is unlisted, false otherwise.
313
     */
314
    public boolean isUnlisted() {
315
        return typeMap.get(templateIri).contains(UNLISTED_TEMPLATE_CLASS);
×
316
    }
317

318
    /**
319
     * Returns the Nanopub object representing the template.
320
     *
321
     * @return the Nanopub object of the template.
322
     */
323
    public Nanopub getNanopub() {
324
        return nanopub;
×
325
    }
326

327
    /**
328
     * Returns the ID of the template, which is the URI of the nanopublication.
329
     *
330
     * @return the ID of the template as a string.
331
     */
332
    public String getId() {
333
        return nanopub.getUri().toString();
×
334
    }
335

336
    /**
337
     * Returns the label of the template.
338
     *
339
     * @return the label of the template, or a default label if not set.
340
     */
341
    public String getLabel() {
342
        if (label == null) {
3!
343
            return "Template " + TrustyUriUtils.getArtifactCode(nanopub.getUri().stringValue()).substring(0, 10);
×
344
        }
345
        return label;
3✔
346
    }
347

348
    /**
349
     * Returns the description of the template.
350
     *
351
     * @return the description of the template, or an empty string if not set.
352
     */
353
    public String getDescription() {
354
        return description;
3✔
355
    }
356

357
    /**
358
     * Returns the IRI of the template.
359
     *
360
     * @param iri the IRI to transform.
361
     * @return the transformed IRI, or the original IRI if no transformation is needed.
362
     */
363
    public String getLabel(IRI iri) {
364
        iri = transform(iri);
×
365
        return labelMap.get(iri);
×
366
    }
367

368
    /**
369
     * Returns the IRI of the template, transforming it if necessary.
370
     *
371
     * @param iri the IRI to transform.
372
     * @return the transformed IRI, or the original IRI if no transformation is needed.
373
     */
374
    public IRI getFirstOccurence(IRI iri) {
375
        for (IRI i : getStatementIris()) {
×
376
            if (statementMap.containsKey(i)) {
×
377
                // grouped statement
378
                for (IRI g : getStatementIris(i)) {
×
379
                    if (iri.equals(statementSubjects.get(g))) return g;
×
380
                    if (iri.equals(statementPredicates.get(g))) return g;
×
381
                    if (iri.equals(statementObjects.get(g))) return g;
×
382
                }
×
383
            } else {
384
                // non-grouped statement
385
                if (iri.equals(statementSubjects.get(i))) return i;
×
386
                if (iri.equals(statementPredicates.get(i))) return i;
×
387
                if (iri.equals(statementObjects.get(i))) return i;
×
388
            }
389
        }
×
390
        return null;
×
391
    }
392

393
    /**
394
     * Returns the datatype for the given literal placeholder IRI.
395
     *
396
     * @param iri the literal placeholder IRI.
397
     * @return the datatype for the literal.
398
     */
399
    public IRI getDatatype(IRI iri) {
400
        iri = transform(iri);
×
401
        return datatypeMap.get(iri);
×
402
    }
403

404
    /**
405
     * Returns the language attribute for the given literal placeholder IRI.
406
     *
407
     * @param iri the literal placeholder IRI.
408
     * @return the language attribute for the literal.
409
     */
410
    public String getLanguageAttribute(IRI iri) {
411
        iri = transform(iri);
×
412
        return languageAttributeMap.get(iri);
×
413
    }
414

415
    /**
416
     * Returns the prefix for the given IRI.
417
     *
418
     * @param iri the IRI.
419
     * @return the prefix for the IRI.
420
     */
421
    public String getPrefix(IRI iri) {
422
        iri = transform(iri);
×
423
        return prefixMap.get(iri);
×
424
    }
425

426
    /**
427
     * Returns the prefix label for a given IRI.
428
     *
429
     * @param iri the IRI to get the prefix label for.
430
     * @return the prefix label for the IRI, or null if not found.
431
     */
432
    public String getPrefixLabel(IRI iri) {
433
        iri = transform(iri);
×
434
        return prefixLabelMap.get(iri);
×
435
    }
436

437
    /**
438
     * Returns the regex pattern for a given IRI.
439
     *
440
     * @param iri the IRI to get the regex for.
441
     * @return the regex pattern for the IRI, or null if not found.
442
     */
443
    public String getRegex(IRI iri) {
444
        iri = transform(iri);
×
445
        return regexMap.get(iri);
×
446
    }
447

448
    /**
449
     * Transforms an IRI by removing the artifact code if it is present.
450
     *
451
     * @param iri the IRI to transform.
452
     * @return the transformed IRI, or the original IRI if no transformation is needed.
453
     */
454
    public Value getDefault(IRI iri) {
455
        if (iri.stringValue().matches(".*__[0-9]+")) {
×
456
            String baseIri = iri.stringValue().replaceFirst("__[0-9]+$", "");
×
457
            Value v = defaultValues.get(vf.createIRI(baseIri));
×
458
            if (v instanceof IRI vIri) {
×
459
                int repeatSuffix = Integer.parseInt(iri.stringValue().replaceFirst("^.*__([0-9]+)$", "$1"));
×
460
                return vf.createIRI(vIri.stringValue() + (repeatSuffix + 1));
×
461
            }
462
        }
463
        iri = transform(iri);
×
464
        return defaultValues.get(iri);
×
465
    }
466

467
    /**
468
     * Returns the statement IRIs associated with the template.
469
     *
470
     * @return the list of statement IRIs for the template.
471
     */
472
    public List<IRI> getStatementIris() {
473
        return statementMap.get(templateIri);
×
474
    }
475

476
    /**
477
     * Returns the statement IRIs associated with a specific group IRI.
478
     *
479
     * @param groupIri the IRI of the group for which to retrieve statement IRIs.
480
     * @return the list of statement IRIs for the specified group IRI, or null if no statements are associated with that group.
481
     */
482
    public List<IRI> getStatementIris(IRI groupIri) {
483
        return statementMap.get(groupIri);
×
484
    }
485

486
    /**
487
     * Returns the subject, predicate, and object of a statement given its IRI.
488
     *
489
     * @param statementIri the IRI of the statement to retrieve.
490
     * @return the subject, predicate, and object of the statement as a triple.
491
     */
492
    public IRI getSubject(IRI statementIri) {
493
        return statementSubjects.get(statementIri);
×
494
    }
495

496
    /**
497
     * Returns the predicate of a statement given its IRI.
498
     *
499
     * @param statementIri the IRI of the statement to retrieve.
500
     * @return the predicate of the statement, or null if not found.
501
     */
502
    public IRI getPredicate(IRI statementIri) {
503
        return statementPredicates.get(statementIri);
×
504
    }
505

506
    /**
507
     * Returns the object of a statement given its IRI.
508
     *
509
     * @param statementIri the IRI of the statement to retrieve.
510
     * @return the object of the statement, or null if not found.
511
     */
512
    public Value getObject(IRI statementIri) {
513
        return statementObjects.get(statementIri);
×
514
    }
515

516
    /**
517
     * Checks if the template is a local resource.
518
     *
519
     * @param iri the IRI to check.
520
     * @return true if the IRI is a local resource, false otherwise.
521
     */
522
    public boolean isLocalResource(IRI iri) {
523
        iri = transform(iri);
×
524
        return typeMap.containsKey(iri) && typeMap.get(iri).contains(LOCAL_RESOURCE_CLASS);
×
525
    }
526

527
    /**
528
     * Checks if the template is an introduced resource.
529
     *
530
     * @param iri the IRI to check.
531
     * @return true if the IRI is an introduced resource, false otherwise.
532
     */
533
    public boolean isIntroducedResource(IRI iri) {
534
        iri = transform(iri);
×
535
        return typeMap.containsKey(iri) && typeMap.get(iri).contains(INTRODUCED_RESOURCE_CLASS);
×
536
    }
537

538
    /**
539
     * Checks if the template is an embedded resource.
540
     *
541
     * @param iri the IRI to check.
542
     * @return true if the IRI is an embedded resource, false otherwise.
543
     */
544
    public boolean isEmbeddedResource(IRI iri) {
545
        iri = transform(iri);
×
546
        return typeMap.containsKey(iri) && typeMap.get(iri).contains(EMBEDDED_RESOURCE_CLASS);
×
547
    }
548

549
    /**
550
     * Checks if the IRI is a value placeholder.
551
     *
552
     * @param iri the IRI to check.
553
     * @return true if the IRI is a value placeholder, false otherwise.
554
     */
555
    public boolean isValuePlaceholder(IRI iri) {
556
        iri = transform(iri);
×
557
        return typeMap.containsKey(iri) && typeMap.get(iri).contains(VALUE_PLACEHOLDER_CLASS);
×
558
    }
559

560
    /**
561
     * Checks if the IRI is a URI placeholder.
562
     *
563
     * @param iri the IRI to check.
564
     * @return true if the IRI is a URI placeholder, false otherwise.
565
     */
566
    public boolean isUriPlaceholder(IRI iri) {
567
        iri = transform(iri);
×
568
        if (!typeMap.containsKey(iri)) return false;
×
569
        for (IRI t : typeMap.get(iri)) {
×
570
            if (t.equals(URI_PLACEHOLDER_CLASS)) return true;
×
571
            if (t.equals(EXTERNAL_URI_PLACEHOLDER_CLASS)) return true;
×
572
            if (t.equals(TRUSTY_URI_PLACEHOLDER_CLASS)) return true;
×
573
            if (t.equals(AUTO_ESCAPE_URI_PLACEHOLDER_CLASS)) return true;
×
574
            if (t.equals(RESTRICTED_CHOICE_PLACEHOLDER_CLASS)) return true;
×
575
            if (t.equals(GUIDED_CHOICE_PLACEHOLDER_CLASS)) return true;
×
576
            if (t.equals(AGENT_PLACEHOLDER_CLASS)) return true;
×
577
        }
×
578
        return false;
×
579
    }
580

581
    /**
582
     * Checks if the IRI is an external URI placeholder.
583
     *
584
     * @param iri the IRI to check.
585
     * @return true if the IRI is an external URI placeholder, false otherwise.
586
     */
587
    public boolean isExternalUriPlaceholder(IRI iri) {
588
        iri = transform(iri);
×
589
        if (!typeMap.containsKey(iri)) return false;
×
590
        for (IRI t : typeMap.get(iri)) {
×
591
            if (t.equals(EXTERNAL_URI_PLACEHOLDER_CLASS)) return true;
×
592
            if (t.equals(TRUSTY_URI_PLACEHOLDER_CLASS)) return true;
×
593
        }
×
594
        return false;
×
595
    }
596

597
    /**
598
     * Checks if the IRI is a trusty URI placeholder.
599
     *
600
     * @param iri the IRI to check.
601
     * @return true if the IRI is a trusty URI placeholder, false otherwise.
602
     */
603
    public boolean isTrustyUriPlaceholder(IRI iri) {
604
        iri = transform(iri);
×
605
        return typeMap.containsKey(iri) && typeMap.get(iri).contains(TRUSTY_URI_PLACEHOLDER_CLASS);
×
606
    }
607

608
    /**
609
     * Checks if the IRI is an auto-escape URI placeholder.
610
     *
611
     * @param iri the IRI to check.
612
     * @return true if the IRI is an auto-escape URI placeholder, false otherwise.
613
     */
614
    public boolean isAutoEscapePlaceholder(IRI iri) {
615
        iri = transform(iri);
×
616
        return typeMap.containsKey(iri) && typeMap.get(iri).contains(AUTO_ESCAPE_URI_PLACEHOLDER_CLASS);
×
617
    }
618

619
    /**
620
     * Checks if the IRI is a literal placeholder.
621
     *
622
     * @param iri the IRI to check.
623
     * @return true if the IRI is a literal placeholder, false otherwise.
624
     */
625
    public boolean isLiteralPlaceholder(IRI iri) {
626
        iri = transform(iri);
×
627
        return typeMap.containsKey(iri) && (typeMap.get(iri).contains(LITERAL_PLACEHOLDER_CLASS) || typeMap.get(iri).contains(LONG_LITERAL_PLACEHOLDER_CLASS));
×
628
    }
629

630
    /**
631
     * Checks if the IRI is a long literal placeholder.
632
     *
633
     * @param iri the IRI to check.
634
     * @return true if the IRI is a long literal placeholder, false otherwise.
635
     */
636
    public boolean isLongLiteralPlaceholder(IRI iri) {
637
        iri = transform(iri);
×
638
        return typeMap.containsKey(iri) && typeMap.get(iri).contains(LONG_LITERAL_PLACEHOLDER_CLASS);
×
639
    }
640

641
    /**
642
     * Checks if the IRI is a restricted choice placeholder.
643
     *
644
     * @param iri the IRI to check.
645
     * @return true if the IRI is a restricted choice placeholder, false otherwise.
646
     */
647
    public boolean isRestrictedChoicePlaceholder(IRI iri) {
648
        iri = transform(iri);
×
649
        return typeMap.containsKey(iri) && typeMap.get(iri).contains(RESTRICTED_CHOICE_PLACEHOLDER_CLASS);
×
650
    }
651

652
    /**
653
     * Checks if the IRI is a guided choice placeholder.
654
     *
655
     * @param iri the IRI to check.
656
     * @return true if the IRI is a guided choice placeholder, false otherwise.
657
     */
658
    public boolean isGuidedChoicePlaceholder(IRI iri) {
659
        iri = transform(iri);
×
660
        return typeMap.containsKey(iri) && typeMap.get(iri).contains(GUIDED_CHOICE_PLACEHOLDER_CLASS);
×
661
    }
662

663
    /**
664
     * Checks if the IRI is an agent placeholder.
665
     *
666
     * @param iri the IRI to check.
667
     * @return true if the IRI is an agent placeholder, false otherwise.
668
     */
669
    public boolean isAgentPlaceholder(IRI iri) {
670
        iri = transform(iri);
×
671
        return typeMap.containsKey(iri) && typeMap.get(iri).contains(AGENT_PLACEHOLDER_CLASS);
×
672
    }
673

674
    /**
675
     * Checks if the IRI is a sequence element placeholder.
676
     *
677
     * @param iri the IRI to check.
678
     * @return true if the IRI is a sequence element placeholder, false otherwise.
679
     */
680
    public boolean isSequenceElementPlaceholder(IRI iri) {
681
        iri = transform(iri);
×
682
        return typeMap.containsKey(iri) && typeMap.get(iri).contains(SEQUENCE_ELEMENT_PLACEHOLDER);
×
683
    }
684

685
    /**
686
     * Checks if the IRI is a placeholder of any type.
687
     *
688
     * @param iri the IRI to check.
689
     * @return true if the IRI is a placeholder, false otherwise.
690
     */
691
    public boolean isPlaceholder(IRI iri) {
692
        iri = transform(iri);
×
693
        if (!typeMap.containsKey(iri)) return false;
×
694
        for (IRI t : typeMap.get(iri)) {
×
695
            if (t.equals(VALUE_PLACEHOLDER_CLASS)) return true;
×
696
            if (t.equals(URI_PLACEHOLDER_CLASS)) return true;
×
697
            if (t.equals(EXTERNAL_URI_PLACEHOLDER_CLASS)) return true;
×
698
            if (t.equals(TRUSTY_URI_PLACEHOLDER_CLASS)) return true;
×
699
            if (t.equals(AUTO_ESCAPE_URI_PLACEHOLDER_CLASS)) return true;
×
700
            if (t.equals(RESTRICTED_CHOICE_PLACEHOLDER_CLASS)) return true;
×
701
            if (t.equals(GUIDED_CHOICE_PLACEHOLDER_CLASS)) return true;
×
702
            if (t.equals(AGENT_PLACEHOLDER_CLASS)) return true;
×
703
            if (t.equals(LITERAL_PLACEHOLDER_CLASS)) return true;
×
704
            if (t.equals(LONG_LITERAL_PLACEHOLDER_CLASS)) return true;
×
705
            if (t.equals(SEQUENCE_ELEMENT_PLACEHOLDER)) return true;
×
706
        }
×
707
        return false;
×
708
    }
709

710
    /**
711
     * Checks if the IRI is an optional statement.
712
     *
713
     * @param iri the IRI to check.
714
     * @return true if the IRI is an optional statement, false otherwise.
715
     */
716
    public boolean isOptionalStatement(IRI iri) {
717
        return typeMap.containsKey(iri) && typeMap.get(iri).contains(OPTIONAL_STATEMENT_CLASS);
×
718
    }
719

720
    /**
721
     * Checks if the IRI is a grouped statement.
722
     *
723
     * @param iri the IRI to check.
724
     * @return true if the IRI is a grouped statement, false otherwise.
725
     */
726
    public boolean isGroupedStatement(IRI iri) {
727
        return typeMap.containsKey(iri) && typeMap.get(iri).contains(GROUPED_STATEMENT_CLASS);
×
728
    }
729

730
    /**
731
     * Checks if the IRI is a repeatable statement.
732
     *
733
     * @param iri the IRI to check.
734
     * @return true if the IRI is a repeatable statement, false otherwise.
735
     */
736
    public boolean isRepeatableStatement(IRI iri) {
737
        return typeMap.containsKey(iri) && typeMap.get(iri).contains(REPEATABLE_STATEMENT_CLASS);
×
738
    }
739

740
    /**
741
     * Returns the possible values for a given IRI.
742
     *
743
     * @param iri the IRI for which to get possible values.
744
     * @return a list of possible values for the IRI. If no values are found, an empty list is returned.
745
     */
746
    public List<Value> getPossibleValues(IRI iri) {
747
        iri = transform(iri);
×
748
        List<Value> l = possibleValueMap.get(iri);
×
749
        if (l == null) {
×
750
            l = new ArrayList<>();
×
751
            possibleValueMap.put(iri, l);
×
752
        }
753
        List<IRI> nanopubList = possibleValuesToLoadMap.get(iri);
×
754
        if (nanopubList != null) {
×
755
            for (IRI npIri : new ArrayList<>(nanopubList)) {
×
756
                try {
757
                    Nanopub valuesNanopub = Utils.getNanopub(npIri.stringValue());
×
758
                    for (Statement st : valuesNanopub.getAssertion()) {
×
759
                        if (st.getPredicate().equals(RDFS.LABEL)) {
×
760
                            l.add((IRI) st.getSubject());
×
761
                        }
762
                    }
×
763
                    nanopubList.remove(npIri);
×
764
                } catch (Exception ex) {
×
765
                    ex.printStackTrace();
×
766
                }
×
767
            }
×
768
        }
769
        return l;
×
770
    }
771

772
    /**
773
     * Returns the IRI of the default provenance for the template.
774
     *
775
     * @return the IRI of the default provenance, or null if not set.
776
     */
777
    public IRI getDefaultProvenance() {
778
        return defaultProvenance;
×
779
    }
780

781
    /**
782
     * Returns the target namespace for the template.
783
     *
784
     * @return the target namespace as a string, or null if not set.
785
     */
786
    public String getTargetNamespace() {
787
        return targetNamespace;
×
788
    }
789

790
    /**
791
     * Returns the nanopub label pattern.
792
     *
793
     * @return the nanopub label pattern as a string, or null if not set.
794
     */
795
    public String getNanopubLabelPattern() {
796
        return nanopubLabelPattern;
3✔
797
    }
798

799
    /**
800
     * Returns the list of target nanopub types.
801
     *
802
     * @return a list of IRI objects representing the target nanopub types.
803
     */
804
    public List<IRI> getTargetNanopubTypes() {
805
        return targetNanopubTypes;
×
806
    }
807

808
    /**
809
     * Returns the list of the required pubinfo elements for the template.
810
     *
811
     * @return a list of IRI objects representing the required pubinfo elements.
812
     */
813
    public List<IRI> getRequiredPubinfoElements() {
814
        return requiredPubinfoElements;
×
815
    }
816

817
    /**
818
     * Returns the possible values from an API for a given IRI and search term.
819
     *
820
     * @param iri        the IRI for which to get possible values from the API.
821
     * @param searchterm the search term to filter the possible values.
822
     * @param labelMap   a map to store labels for the possible values.
823
     * @return a list of possible values from the API, filtered by the search term.
824
     */
825
    public List<String> getPossibleValuesFromApi(IRI iri, String searchterm, Map<String, String> labelMap) {
826
        iri = transform(iri);
×
827
        List<String> values = new ArrayList<>();
×
828
        List<String> apiList = apiMap.get(iri);
×
829
        if (apiList != null) {
×
830
            for (String apiString : apiList) {
×
831
                LookupApis.getPossibleValues(apiString, searchterm, labelMap, values);
×
832
            }
×
833
        }
834
        return values;
×
835
    }
836

837
    /**
838
     * Returns the tag associated with the template.
839
     *
840
     * @return the tag as a string, or null if not set.
841
     */
842
    public String getTag() {
843
        return tag;
3✔
844
    }
845

846
    private void processTemplate(Nanopub templateNp) throws MalformedTemplateException {
847
        boolean isNpTemplate = false;
2✔
848
        for (Statement st : templateNp.getAssertion()) {
11!
849
            if (st.getSubject().equals(templateNp.getAssertionUri()) && st.getPredicate().equals(RDF.TYPE)) {
11!
850
                if (st.getObject().equals(ASSERTION_TEMPLATE_CLASS) || st.getObject().equals(PROVENANCE_TEMPLATE_CLASS) || st.getObject().equals(PUBINFO_TEMPLATE_CLASS)) {
5!
851
                    isNpTemplate = true;
2✔
852
                    break;
1✔
853
                }
854
            }
855
        }
1✔
856

857
        if (isNpTemplate) {
2!
858
            processNpTemplate(templateNp);
4✔
859
        } else {
860
            // Experimental SHACL-based template:
861
            processShaclTemplate(templateNp);
×
862
        }
863
    }
1✔
864

865
    private void processNpTemplate(Nanopub templateNp) throws MalformedTemplateException {
866
        templateIri = templateNp.getAssertionUri();
4✔
867
        for (Statement st : templateNp.getAssertion()) {
11✔
868
            final IRI subj = (IRI) st.getSubject();
4✔
869
            final IRI pred = st.getPredicate();
3✔
870
            final Value obj = st.getObject();
3✔
871
            final String objS = obj.stringValue();
3✔
872

873
            if (subj.equals(templateIri)) {
5✔
874
                if (pred.equals(RDFS.LABEL)) {
4✔
875
                    label = objS;
4✔
876
                } else if (pred.equals(DCTERMS.DESCRIPTION)) {
4✔
877
                    description = Utils.sanitizeHtml(objS);
5✔
878
                } else if (obj instanceof IRI objIri) {
6✔
879
                    if (pred.equals(HAS_DEFAULT_PROVENANCE_PREDICATE)) {
4!
880
                        defaultProvenance = objIri;
×
881
                    } else if (pred.equals(HAS_REQUIRED_PUBINFO_ELEMENT_PREDICATE)) {
4!
882
                        requiredPubinfoElements.add(objIri);
×
883
                    } else if (pred.equals(HAS_TARGET_NAMESPACE)) {
4!
884
                        targetNamespace = objS;
×
885
                    } else if (pred.equals(HAS_TARGET_NANOPUB_TYPE)) {
4!
886
                        targetNanopubTypes.add(objIri);
×
887
                    }
888
                } else if (obj instanceof Literal) {
3!
889
                    if (pred.equals(HAS_TAG)) {
4✔
890
                        // TODO This should be replaced at some point with a more sophisticated mechanism based on classes.
891
                        // We are assuming that there is at most one tag.
892
                        this.tag = objS;
4✔
893
                    } else if (pred.equals(HAS_NANOPUB_LABEL_PATTERN)) {
4!
894
                        nanopubLabelPattern = objS;
3✔
895
                    }
896
                }
897
            }
898
            if (pred.equals(RDF.TYPE) && obj instanceof IRI objIri) {
10!
899
                addType(subj, objIri);
5✔
900
            } else if (pred.equals(HAS_STATEMENT_PREDICATE) && obj instanceof IRI objIri) {
10!
901
                List<IRI> l = statementMap.get(subj);
6✔
902
                if (l == null) {
2✔
903
                    l = new ArrayList<>();
4✔
904
                    statementMap.put(subj, l);
6✔
905
                }
906
                l.add((IRI) objIri);
4✔
907
            } else if (pred.equals(POSSIBLE_VALUE_PREDICATE)) {
5!
908
                List<Value> l = possibleValueMap.get(subj);
×
909
                if (l == null) {
×
910
                    l = new ArrayList<>();
×
911
                    possibleValueMap.put(subj, l);
×
912
                }
913
                l.add(obj);
×
914
            } else if (pred.equals(POSSIBLE_VALUES_FROM_PREDICATE)) {
4!
915
                List<IRI> l = possibleValuesToLoadMap.get(subj);
×
916
                if (l == null) {
×
917
                    l = new ArrayList<>();
×
918
                    possibleValuesToLoadMap.put(subj, l);
×
919
                }
920
                if (obj instanceof IRI objIri) {
×
921
                    l.add(objIri);
×
922
                    Nanopub valuesNanopub = Utils.getNanopub(objS);
×
923
                    for (Statement s : valuesNanopub.getAssertion()) {
×
924
                        if (s.getPredicate().equals(RDFS.LABEL)) {
×
925
                            labelMap.put((IRI) s.getSubject(), s.getObject().stringValue());
×
926
                        }
927
                    }
×
928
                }
929
            } else if (pred.equals(POSSIBLE_VALUES_FROM_API_PREDICATE)) {
4✔
930
                List<String> l = apiMap.get(subj);
6✔
931
                if (l == null) {
2✔
932
                    l = new ArrayList<>();
4✔
933
                    apiMap.put(subj, l);
6✔
934
                }
935
                if (obj instanceof Literal) {
3!
936
                    l.add(objS);
4✔
937
                }
938
            } else if (pred.equals(RDFS.LABEL) && obj instanceof Literal) {
8!
939
                labelMap.put(subj, objS);
7✔
940
            } else if (pred.equals(HAS_DATATYPE_PREDICATE) && obj instanceof IRI objIri) {
4!
941
                    datatypeMap.put(subj, objIri);
×
942
            } else if (pred.equals(HAS_LANGUATE_ATTRIBUTE_PREDICATE) && obj instanceof Literal) {
4!
943
                    languageAttributeMap.put(subj, Literals.normalizeLanguageTag(objS));
×
944
            } else if (pred.equals(HAS_PREFIX_PREDICATE) && obj instanceof Literal) {
4!
945
                prefixMap.put(subj, objS);
×
946
            } else if (pred.equals(HAS_PREFIX_LABEL_PREDICATE) && obj instanceof Literal) {
4!
947
                prefixLabelMap.put(subj, objS);
×
948
            } else if (pred.equals(HAS_REGEX_PREDICATE) && obj instanceof Literal) {
4!
949
                regexMap.put(subj, objS);
×
950
            } else if (pred.equals(RDF.SUBJECT) && obj instanceof IRI objIri) {
10!
951
                statementSubjects.put(subj, objIri);
7✔
952
            } else if (pred.equals(RDF.PREDICATE) && obj instanceof IRI objIri) {
10!
953
                statementPredicates.put(subj, objIri);
7✔
954
            } else if (pred.equals(RDF.OBJECT)) {
4✔
955
                statementObjects.put(subj, obj);
7✔
956
            } else if (pred.equals(HAS_DEFAULT_VALUE)) {
4!
957
                defaultValues.put(subj, obj);
×
958
            } else if (pred.equals(STATEMENT_ORDER_PREDICATE)) {
4!
959
                if (obj instanceof Literal && objS.matches("[0-9]+")) {
×
960
                    statementOrder.put(subj, Integer.valueOf(objS));
×
961
                }
962
            }
963
        }
1✔
964
//                List<IRI> assertionTypes = typeMap.get(templateIri);
965
//                if (assertionTypes == null || (!assertionTypes.contains(ASSERTION_TEMPLATE_CLASS) &&
966
//                                !assertionTypes.contains(PROVENANCE_TEMPLATE_CLASS) && !assertionTypes.contains(PUBINFO_TEMPLATE_CLASS))) {
967
//                        throw new MalformedTemplateException("Unknown template type");
968
//                }
969
        for (List<IRI> l : statementMap.values()) {
12✔
970
            l.sort(statementComparator);
4✔
971
        }
1✔
972
    }
1✔
973

974
    private void processShaclTemplate(Nanopub templateNp) throws MalformedTemplateException {
975
        templateIri = null;
×
976
        for (Statement st : templateNp.getAssertion()) {
×
977
            if (st.getPredicate().equals(SHACL.TARGET_CLASS)) {
×
978
                templateIri = (IRI) st.getSubject();
×
979
                break;
×
980
            }
981
        }
×
982
        if (templateIri == null) {
×
983
            throw new MalformedTemplateException("Base node shape not found");
×
984
        }
985

986
        IRI baseSubj = vf.createIRI(templateIri.stringValue() + "+subj");
×
987
        addType(baseSubj, INTRODUCED_RESOURCE_CLASS);
×
988

989
        List<IRI> statementList = new ArrayList<>();
×
990
        Map<IRI, Integer> minCounts = new HashMap<>();
×
991
        Map<IRI, Integer> maxCounts = new HashMap<>();
×
992

993
        for (Statement st : templateNp.getAssertion()) {
×
994
            final IRI subj = (IRI) st.getSubject();
×
995
            final IRI pred = st.getPredicate();
×
996
            final Value obj = st.getObject();
×
997
            final String objS = obj.stringValue();
×
998

999
            if (subj.equals(templateIri)) {
×
1000
                if (pred.equals(RDFS.LABEL)) {
×
1001
                    label = objS;
×
1002
                } else if (pred.equals(DCTERMS.DESCRIPTION)) {
×
1003
                    description = Utils.sanitizeHtml(objS);
×
1004
                } else if (obj instanceof IRI objIri) {
×
1005
                    if (pred.equals(HAS_DEFAULT_PROVENANCE_PREDICATE)) {
×
1006
                        defaultProvenance = objIri;
×
1007
                    } else if (pred.equals(HAS_REQUIRED_PUBINFO_ELEMENT_PREDICATE)) {
×
1008
                        requiredPubinfoElements.add(objIri);
×
1009
                    } else if (pred.equals(HAS_TARGET_NAMESPACE)) {
×
1010
                        targetNamespace = objS;
×
1011
                    } else if (pred.equals(HAS_TARGET_NANOPUB_TYPE)) {
×
1012
                        targetNanopubTypes.add(objIri);
×
1013
                    }
1014
                } else if (obj instanceof Literal) {
×
1015
                    if (pred.equals(HAS_TAG)) {
×
1016
                        // TODO This should be replaced at some point with a more sophisticated mechanism based on classes.
1017
                        // We are assuming that there is at most one tag.
1018
                        this.tag = objS;
×
1019
                    } else if (pred.equals(HAS_NANOPUB_LABEL_PATTERN)) {
×
1020
                        nanopubLabelPattern = objS;
×
1021
                    }
1022
                }
1023
            }
1024
            if (pred.equals(RDF.TYPE) && obj instanceof IRI objIri) {
×
1025
                addType(subj, objIri);
×
1026
            } else if (pred.equals(SHACL.PROPERTY) && obj instanceof IRI objIri) {
×
1027
                statementList.add(objIri);
×
1028
                List<IRI> l = statementMap.get(subj);
×
1029
                if (l == null) {
×
1030
                    l = new ArrayList<>();
×
1031
                    statementMap.put(subj, l);
×
1032
                }
1033
                l.add((IRI) objIri);
×
1034
                IRI stSubjIri = vf.createIRI(subj.stringValue() + "+subj");
×
1035
                statementSubjects.put(objIri, stSubjIri);
×
1036
                addType(stSubjIri, LOCAL_RESOURCE_CLASS);
×
1037
                addType(stSubjIri, URI_PLACEHOLDER_CLASS);
×
1038
            } else if (pred.equals(SHACL.PATH) && obj instanceof IRI objIri) {
×
1039
                statementPredicates.put(subj, objIri);
×
1040
            } else if (pred.equals(SHACL.HAS_VALUE) && obj instanceof IRI objIri) {
×
1041
                statementObjects.put(subj, objIri);
×
1042
            } else if (pred.equals(SHACL.TARGET_CLASS) && obj instanceof IRI objIri) {
×
1043
                IRI stIri = vf.createIRI(templateNp.getUri() + "/$type");
×
1044
                statementList.add(stIri);
×
1045
                List<IRI> l = statementMap.get(subj);
×
1046
                if (l == null) {
×
1047
                    l = new ArrayList<>();
×
1048
                    statementMap.put(subj, l);
×
1049
                }
1050
                l.add((IRI) stIri);
×
1051
                statementSubjects.put(stIri, baseSubj);
×
1052
                statementPredicates.put(stIri, RDF.TYPE);
×
1053
                statementObjects.put(stIri, objIri);
×
1054
            } else if (pred.equals(POSSIBLE_VALUE_PREDICATE)) {
×
1055
                List<Value> l = possibleValueMap.get(subj);
×
1056
                if (l == null) {
×
1057
                    l = new ArrayList<>();
×
1058
                    possibleValueMap.put(subj, l);
×
1059
                }
1060
                l.add(obj);
×
1061
            } else if (pred.equals(POSSIBLE_VALUES_FROM_PREDICATE)) {
×
1062
                List<IRI> l = possibleValuesToLoadMap.get(subj);
×
1063
                if (l == null) {
×
1064
                    l = new ArrayList<>();
×
1065
                    possibleValuesToLoadMap.put(subj, l);
×
1066
                }
1067
                if (obj instanceof IRI objIri) {
×
1068
                    l.add(objIri);
×
1069
                    Nanopub valuesNanopub = Utils.getNanopub(objS);
×
1070
                    for (Statement s : valuesNanopub.getAssertion()) {
×
1071
                        if (s.getPredicate().equals(RDFS.LABEL)) {
×
1072
                            labelMap.put((IRI) s.getSubject(), s.getObject().stringValue());
×
1073
                        }
1074
                    }
×
1075
                }
1076
            } else if (pred.equals(POSSIBLE_VALUES_FROM_API_PREDICATE)) {
×
1077
                List<String> l = apiMap.get(subj);
×
1078
                if (l == null) {
×
1079
                    l = new ArrayList<>();
×
1080
                    apiMap.put(subj, l);
×
1081
                }
1082
                if (obj instanceof Literal) {
×
1083
                    l.add(objS);
×
1084
                }
1085
            } else if (pred.equals(RDFS.LABEL) && obj instanceof Literal) {
×
1086
                labelMap.put(subj, objS);
×
1087
            } else if (pred.equals(HAS_DATATYPE_PREDICATE) && obj instanceof IRI objIri) {
×
1088
                    datatypeMap.put(subj, objIri);
×
1089
            } else if (pred.equals(HAS_LANGUATE_ATTRIBUTE_PREDICATE) && obj instanceof Literal) {
×
1090
                    languageAttributeMap.put(subj,  Literals.normalizeLanguageTag(objS));
×
1091
            } else if (pred.equals(HAS_PREFIX_PREDICATE) && obj instanceof Literal) {
×
1092
                prefixMap.put(subj, objS);
×
1093
            } else if (pred.equals(HAS_PREFIX_LABEL_PREDICATE) && obj instanceof Literal) {
×
1094
                prefixLabelMap.put(subj, objS);
×
1095
            } else if (pred.equals(HAS_REGEX_PREDICATE) && obj instanceof Literal) {
×
1096
                regexMap.put(subj, objS);
×
1097
//                        } else if (pred.equals(RDF.SUBJECT) && obj instanceof IRI objIri) {
1098
//                                statementSubjects.put(subj, objIri);
1099
//                        } else if (pred.equals(RDF.PREDICATE) && obj instanceof IRI objIri) {
1100
//                                statementPredicates.put(subj, objIri);
1101
//                        } else if (pred.equals(RDF.OBJECT)) {
1102
//                                statementObjects.put(subj, obj);
1103
            } else if (pred.equals(HAS_DEFAULT_VALUE)) {
×
1104
                defaultValues.put(subj, obj);
×
1105
            } else if (pred.equals(STATEMENT_ORDER_PREDICATE)) {
×
1106
                if (obj instanceof Literal && objS.matches("[0-9]+")) {
×
1107
                    statementOrder.put(subj, Integer.valueOf(objS));
×
1108
                }
1109
            } else if (pred.equals(SHACL.MIN_COUNT)) {
×
1110
                try {
1111
                    minCounts.put(subj, Integer.parseInt(obj.stringValue()));
×
1112
                } catch (NumberFormatException ex) {
×
1113
                    ex.printStackTrace();
×
1114
                }
×
1115
            } else if (pred.equals(SHACL.MAX_COUNT)) {
×
1116
                try {
1117
                    maxCounts.put(subj, Integer.parseInt(obj.stringValue()));
×
1118
                } catch (NumberFormatException ex) {
×
1119
                    ex.printStackTrace();
×
1120
                }
×
1121
            }
1122
        }
×
1123
        for (List<IRI> l : statementMap.values()) {
×
1124
            l.sort(statementComparator);
×
1125
        }
×
1126
        for (IRI iri : statementList) {
×
1127
            if (!statementObjects.containsKey(iri)) {
×
1128
                IRI stObjIri = vf.createIRI(iri.stringValue() + "+obj");
×
1129
                statementObjects.put(iri, stObjIri);
×
1130
                addType(stObjIri, VALUE_PLACEHOLDER_CLASS);
×
1131
                if (!minCounts.containsKey(iri) || minCounts.get(iri) <= 0) {
×
1132
                    addType(iri, OPTIONAL_STATEMENT_CLASS);
×
1133
                }
1134
                if (!maxCounts.containsKey(iri) || maxCounts.get(iri) > 1) {
×
1135
                    addType(iri, REPEATABLE_STATEMENT_CLASS);
×
1136
                }
1137
            }
1138
        }
×
1139
        if (!labelMap.containsKey(baseSubj) && typeMap.get(baseSubj).contains(URI_PLACEHOLDER_CLASS) && typeMap.get(baseSubj).contains(LOCAL_RESOURCE_CLASS)) {
×
1140
            labelMap.put(baseSubj, "short ID as URI suffix");
×
1141
        }
1142

1143
        if (label == null) {
×
1144
            label = NanopubUtils.getLabel(templateNp);
×
1145
        }
1146
    }
×
1147

1148
    private void addType(IRI thing, IRI type) {
1149
        List<IRI> l = typeMap.get(thing);
6✔
1150
        if (l == null) {
2✔
1151
            l = new ArrayList<>();
4✔
1152
            typeMap.put(thing, l);
6✔
1153
        }
1154
        l.add(type);
4✔
1155
    }
1✔
1156

1157
    private void addStatement(IRI thing, IRI type) {
1158
        List<IRI> l = typeMap.get(thing);
×
1159
        if (l == null) {
×
1160
            l = new ArrayList<>();
×
1161
            typeMap.put(thing, l);
×
1162
        }
1163
        l.add(type);
×
1164
    }
×
1165

1166
    private IRI transform(IRI iri) {
1167
        if (iri.stringValue().matches(".*__[0-9]+")) {
×
1168
            // TODO: Check that this double-underscore pattern isn't used otherwise:
1169
            return vf.createIRI(iri.stringValue().replaceFirst("__[0-9]+$", ""));
×
1170
        }
1171
        return iri;
×
1172
    }
1173

1174

1175
    private StatementComparator statementComparator = new StatementComparator();
6✔
1176

1177
    private class StatementComparator implements Comparator<IRI>, Serializable {
6✔
1178

1179
        private static final long serialVersionUID = 1L;
1180

1181
        /**
1182
         * Compares two IRIs based on their order in the template.
1183
         *
1184
         * @param arg0 the first object to be compared.
1185
         * @param arg1 the second object to be compared.
1186
         * @return a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
1187
         */
1188
        @Override
1189
        public int compare(IRI arg0, IRI arg1) {
1190
            Integer i0 = statementOrder.get(arg0);
7✔
1191
            Integer i1 = statementOrder.get(arg1);
7✔
1192
            if (i0 == null && i1 == null) return arg0.stringValue().compareTo(arg1.stringValue());
10!
1193
            if (i0 == null) return 1;
×
1194
            if (i1 == null) return -1;
×
1195
            return i0 - i1;
×
1196
        }
1197

1198
    }
1199

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