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

knowledgepixels / nanodash / 21406524015

27 Jan 2026 05:02PM UTC coverage: 15.111% (+0.8%) from 14.27%
21406524015

push

github

tkuhn
feat: Support for "advanced" statements, hidden in collapsed view

590 of 5080 branches covered (11.61%)

Branch coverage included in aggregate %.

1584 of 9307 relevant lines covered (17.02%)

2.21 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/StatementItem.java
1
package com.knowledgepixels.nanodash.component;
2

3
import com.knowledgepixels.nanodash.template.ContextType;
4
import com.knowledgepixels.nanodash.template.Template;
5
import com.knowledgepixels.nanodash.template.TemplateContext;
6
import com.knowledgepixels.nanodash.template.UnificationException;
7
import org.apache.wicket.AttributeModifier;
8
import org.apache.wicket.ajax.AjaxEventBehavior;
9
import org.apache.wicket.ajax.AjaxRequestTarget;
10
import org.apache.wicket.behavior.AttributeAppender;
11
import org.apache.wicket.markup.html.WebMarkupContainer;
12
import org.apache.wicket.markup.html.basic.Label;
13
import org.apache.wicket.markup.html.list.ListItem;
14
import org.apache.wicket.markup.html.list.ListView;
15
import org.apache.wicket.markup.html.panel.Panel;
16
import org.apache.wicket.model.IModel;
17
import org.eclipse.rdf4j.model.IRI;
18
import org.eclipse.rdf4j.model.Statement;
19
import org.eclipse.rdf4j.model.Value;
20
import org.eclipse.rdf4j.model.ValueFactory;
21
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
22
import org.nanopub.MalformedNanopubException;
23
import org.nanopub.NanopubAlreadyFinalizedException;
24
import org.nanopub.NanopubCreator;
25
import org.nanopub.vocabulary.NTEMPLATE;
26
import org.slf4j.Logger;
27
import org.slf4j.LoggerFactory;
28

29
import java.io.Serializable;
30
import java.util.*;
31

32
/**
33
 * Represents a single item in a statement, which can be a subject, predicate, or object.
34
 */
35
public class StatementItem extends Panel {
36

37
    private TemplateContext context;
38
    private IRI statementId;
39
    private List<IRI> statementPartIds = new ArrayList<>();
×
40
    private List<WebMarkupContainer> viewElements = new ArrayList<>();
×
41
    private List<RepetitionGroup> repetitionGroups = new ArrayList<>();
×
42
    private boolean repetitionGroupsChanged = true;
×
43
    private Set<IRI> iriSet = new HashSet<>();
×
44
    private boolean isMatched = false;
×
45
    private static final Logger logger = LoggerFactory.getLogger(StatementItem.class);
×
46

47
    /**
48
     * Constructor for creating a StatementItem with a specific ID and statement ID.
49
     *
50
     * @param id          the Wicket component ID
51
     * @param statementId the IRI of the statement this item represents
52
     * @param context     the template context containing information about the template and its items
53
     */
54
    public StatementItem(String id, IRI statementId, TemplateContext context) {
55
        super(id);
×
56

57
        this.statementId = statementId;
×
58
        this.context = context;
×
59
        setOutputMarkupId(true);
×
60

61
        if (isGrouped()) {
×
62
            statementPartIds.addAll(getTemplate().getStatementIris(statementId));
×
63
        } else {
64
            statementPartIds.add(statementId);
×
65
        }
66

67
        addRepetitionGroup();
×
68

69
        ListView<WebMarkupContainer> v = new ListView<WebMarkupContainer>("statement-group", viewElements) {
×
70

71
            @Override
72
            protected void populateItem(ListItem<WebMarkupContainer> item) {
73
                item.add(item.getModelObject());
×
74
            }
×
75

76
        };
77
        v.setOutputMarkupId(true);
×
78
        add(v);
×
79
    }
×
80

81
    /**
82
     * Adds a new repetition group to this StatementItem with a default RepetitionGroup.
83
     */
84
    public void addRepetitionGroup() {
85
        addRepetitionGroup(new RepetitionGroup());
×
86
    }
×
87

88
    /**
89
     * Adds a new repetition group to this StatementItem.
90
     *
91
     * @param rg the RepetitionGroup to add
92
     */
93
    public void addRepetitionGroup(RepetitionGroup rg) {
94
        repetitionGroups.add(rg);
×
95
        repetitionGroupsChanged = true;
×
96
    }
×
97

98
    /**
99
     * {@inheritDoc}
100
     */
101
    @Override
102
    protected void onBeforeRender() {
103
        if (repetitionGroupsChanged) {
×
104
            updateViewElements();
×
105
            finalizeValues();
×
106
        }
107
        repetitionGroupsChanged = false;
×
108
        super.onBeforeRender();
×
109
    }
×
110

111
    private void updateViewElements() {
112
        viewElements.clear();
×
113
        boolean first = true;
×
114
        for (RepetitionGroup r : repetitionGroups) {
×
115
            if (isGrouped() && !first) {
×
116
                viewElements.add(new HorizontalLine("statement"));
×
117
            }
118
            viewElements.addAll(r.getStatementParts());
×
119
            boolean isOnly = repetitionGroups.size() == 1;
×
120
            boolean isLast = repetitionGroups.get(repetitionGroups.size() - 1) == r;
×
121
            r.addRepetitionButton.setVisible(!context.isReadOnly() && isRepeatable() && isLast);
×
122
            r.removeRepetitionButton.setVisible(!context.isReadOnly() && isRepeatable() && !isOnly);
×
123
            r.optionalMark.setVisible(isOnly);
×
124
            first = false;
×
125
        }
×
126
        String htmlClassString = "";
×
127
        if (!context.isReadOnly()) {
×
128
            if (isOptional()) {
×
129
                htmlClassString += "nanopub-optional ";
×
130
            }
131
            if (isAdvanced()) {
×
132
                htmlClassString += "advanced ";
×
133
            }
134
        }
135
        boolean singleItem = context.getStatementItems().size() == 1;
×
136
        boolean repeatableOrRepeated = (!context.isReadOnly() && isRepeatable()) || (context.isReadOnly() && getRepetitionCount() > 1);
×
137
        if ((isGrouped() || repeatableOrRepeated) && !singleItem) {
×
138
            htmlClassString += "nanopub-group ";
×
139
        }
140
        if (!htmlClassString.isEmpty()) {
×
141
            add(new AttributeModifier("class", htmlClassString));
×
142
        }
143
    }
×
144

145
    /**
146
     * Adds the triples of this statement item to the given NanopubCreator.
147
     *
148
     * @param npCreator the NanopubCreator to which the triples will be added
149
     * @throws org.nanopub.MalformedNanopubException        if the statement item is not properly set up
150
     * @throws org.nanopub.NanopubAlreadyFinalizedException if the NanopubCreator has already been finalized
151
     */
152
    public void addTriplesTo(NanopubCreator npCreator) throws MalformedNanopubException, NanopubAlreadyFinalizedException {
153
        if (hasEmptyElements()) {
×
154
            if (isOptional()) {
×
155
                return;
×
156
            } else {
157
                throw new MalformedNanopubException("Field of statement not set.");
×
158
            }
159
        }
160
        for (RepetitionGroup rg : repetitionGroups) {
×
161
            rg.addTriplesTo(npCreator);
×
162
        }
×
163
    }
×
164

165
    private Template getTemplate() {
166
        return context.getTemplate();
×
167
    }
168

169
    /**
170
     * Returns the number of the repetition groups for this statement item.
171
     *
172
     * @return the number of repetition groups
173
     */
174
    public int getRepetitionCount() {
175
        return repetitionGroups.size();
×
176
    }
177

178
    /**
179
     * Returns whether the statement is optional.
180
     */
181
    public boolean isOptional() {
182
        return repetitionGroups.size() == 1 && getTemplate().isOptionalStatement(statementId);
×
183
    }
184

185
    /**
186
     * Returns whether the statement is advanced.
187
     */
188
    public boolean isAdvanced() {
189
        return getTemplate().isAdvancedStatement(statementId);
×
190
    }
191

192
    /**
193
     * Checks if this statement item is grouped.
194
     *
195
     * @return true if the statement item is grouped, false otherwise
196
     */
197
    public boolean isGrouped() {
198
        return getTemplate().isGroupedStatement(statementId);
×
199
    }
200

201
    /**
202
     * Checks if this statement item is repeatable.
203
     *
204
     * @return true if the statement item is repeatable, false otherwise
205
     */
206
    public boolean isRepeatable() {
207
        return getTemplate().isRepeatableStatement(statementId);
×
208
    }
209

210
    /**
211
     * Checks if this statement item has empty elements.
212
     *
213
     * @return true if any of the repetition groups has empty elements, false otherwise
214
     */
215
    public boolean hasEmptyElements() {
216
        return repetitionGroups.get(0).hasEmptyElements();
×
217
    }
218

219
    /**
220
     * Returns the set of IRIs associated with this statement item.
221
     *
222
     * @return a set of IRIs
223
     */
224
    public Set<IRI> getIriSet() {
225
        return iriSet;
×
226
    }
227

228
    /**
229
     * Checks if this statement item will match any triple.
230
     *
231
     * @return true if it will match any triple, false otherwise
232
     */
233
    public boolean willMatchAnyTriple() {
234
        return repetitionGroups.get(0).matches(dummyStatementList);
×
235
    }
236

237
    /**
238
     * Fills this statement item with the provided list of statements, matching them against the repetition groups.
239
     *
240
     * @param statements the list of statements to match against
241
     * @throws com.knowledgepixels.nanodash.template.UnificationException if the statements cannot be unified with this statement item
242
     */
243
    public void fill(List<Statement> statements) throws UnificationException {
244
        if (isMatched) return;
×
245
        if (repetitionGroups.size() == 1) {
×
246
            RepetitionGroup rg = repetitionGroups.get(0);
×
247
            if (rg.matches(statements)) {
×
248
                rg.fill(statements);
×
249
            } else {
250
                return;
×
251
            }
252
        } else {
×
253
            return;
×
254
        }
255
        isMatched = true;
×
256
        if (!isRepeatable()) return;
×
257
        while (true) {
258
            RepetitionGroup newGroup = new RepetitionGroup();
×
259
            if (newGroup.matches(statements)) {
×
260
                newGroup.fill(statements);
×
261
                addRepetitionGroup(newGroup);
×
262
            } else {
263
                newGroup.disconnect();
×
264
                return;
×
265
            }
266
        }
×
267
    }
268

269
    /**
270
     * Marks the filling of this statement item as finished, indicating that all values have been filled.
271
     */
272
    public void fillFinished() {
273
        for (RepetitionGroup rg : repetitionGroups) {
×
274
            rg.fillFinished();
×
275
        }
×
276
    }
×
277

278
    /**
279
     * Finalizes the values of all ValueItems in this statement item.
280
     */
281
    public void finalizeValues() {
282
        for (RepetitionGroup rg : repetitionGroups) {
×
283
            rg.finalizeValues();
×
284
        }
×
285
    }
×
286

287
    /**
288
     * Returns true if the statement item has been matched with a set of statements.
289
     *
290
     * @return true if matched, false otherwise
291
     */
292
    public boolean isMatched() {
293
        return isMatched;
×
294
    }
295

296
    /**
297
     * Checks if this statement item is empty, meaning it has no filled repetition groups.
298
     *
299
     * @return true if the statement item is empty, false otherwise
300
     */
301
    public boolean isEmpty() {
302
        return repetitionGroups.size() == 1 && repetitionGroups.get(0).isEmpty();
×
303
    }
304

305
    /**
306
     * Represents a group of repetitions for a statement item, containing multiple statement parts.
307
     */
308
    public class RepetitionGroup implements Serializable {
309

310
        private List<StatementPartItem> statementParts;
311
        private List<ValueItem> localItems = new ArrayList<>();
×
312
        private boolean filled = false;
×
313

314
        private List<ValueItem> items = new ArrayList<>();
×
315

316
        Label addRepetitionButton, removeRepetitionButton, optionalMark;
317

318
        /**
319
         * Constructor for creating a RepetitionGroup.
320
         */
321
        public RepetitionGroup() {
×
322
            statementParts = new ArrayList<>();
×
323
            for (IRI s : statementPartIds) {
×
324
                StatementPartItem statement = new StatementPartItem("statement",
×
325
                        makeValueItem("subj", getTemplate().getSubject(s), s),
×
326
                        makeValueItem("pred", getTemplate().getPredicate(s), s),
×
327
                        makeValueItem("obj", getTemplate().getObject(s), s)
×
328
                );
329
                statementParts.add(statement);
×
330

331
                // Some of the methods of StatementItem and RepetitionGroup don't work properly before this
332
                // object is fully instantiated:
333
                boolean isFirstGroup = repetitionGroups.isEmpty();
×
334
                boolean isFirstLine = statementParts.size() == 1;
×
335
                boolean isLastLine = statementParts.size() == statementPartIds.size();
×
336
                boolean isOptional = getTemplate().isOptionalStatement(statementId);
×
337

338
                if (statementParts.size() == 1 && !isFirstGroup) {
×
339
                    statement.add(new AttributeAppender("class", " separate-statement"));
×
340
                }
341
                if (!context.isReadOnly()) {
×
342
                    if (isOptional && isLastLine) {
×
343
                        if (isAdvanced()) {
×
344
                            optionalMark = new Label("label", "(optional, advanced)");
×
345
                        } else {
346
                            optionalMark = new Label("label", "(optional)");
×
347
                        }
348
                    } else if (isAdvanced()) {
×
349
                        optionalMark = new Label("label", "(advanced)");
×
350
                    } else {
351
                        optionalMark = new Label("label", "");
×
352
                        optionalMark.setVisible(false);
×
353
                    }
354
                }
355
                statement.add(optionalMark);
×
356
                if (isLastLine) {
×
357
                    addRepetitionButton = new Label("add-repetition", "+");
×
358
                    statement.add(addRepetitionButton);
×
359
                    addRepetitionButton.add(new AjaxEventBehavior("click") {
×
360

361
                        @Override
362
                        protected void onEvent(AjaxRequestTarget target) {
363
                            addRepetitionGroup(new RepetitionGroup());
×
364
                            target.add(StatementItem.this);
×
365
                            target.appendJavaScript("updateElements();");
×
366
                        }
×
367

368
                    });
369
                } else {
370
                    statement.add(new Label("add-repetition", "").setVisible(false));
×
371
                }
372
                if (isFirstLine) {
×
373
                    removeRepetitionButton = new Label("remove-repetition", "-");
×
374
                    statement.add(removeRepetitionButton);
×
375
                    removeRepetitionButton.add(new AjaxEventBehavior("click") {
×
376

377
                        @Override
378
                        protected void onEvent(AjaxRequestTarget target) {
379
                            RepetitionGroup.this.remove();
×
380
                            target.appendJavaScript("updateElements();");
×
381
                            target.add(StatementItem.this);
×
382
                        }
×
383

384
                    });
385
                } else {
386
                    statement.add(new Label("remove-repetition", "").setVisible(false));
×
387
                }
388
            }
×
389
        }
×
390

391
        private ValueItem makeValueItem(String id, Value value, IRI statementPartId) {
392
            if (isFirst() && value instanceof IRI) {
×
393
                iriSet.add((IRI) value);
×
394
            }
395
            ValueItem vi = new ValueItem(id, transform(value), statementPartId, this);
×
396
            localItems.add(vi);
×
397
            items.add(vi);
×
398
            return vi;
×
399
        }
400

401
        private void disconnect() {
402
            for (ValueItem vi : new ArrayList<>(localItems)) {
×
403
                // TODO These remove operations on list are slow. Improve:
404
                localItems.remove(vi);
×
405
                items.remove(vi);
×
406
                vi.removeFromContext();
×
407
            }
×
408
        }
×
409

410
        /**
411
         * Returns the statement parts.
412
         *
413
         * @return a list of StatementPartItem objects representing the statement parts
414
         */
415
        public List<StatementPartItem> getStatementParts() {
416
            return statementParts;
×
417
        }
418

419
        /**
420
         * Returns the index of this repetition group in the list of repetition groups.
421
         *
422
         * @return the index of this repetition group
423
         */
424
        public int getRepeatIndex() {
425
            if (!repetitionGroups.contains(this)) return repetitionGroups.size();
×
426
            return repetitionGroups.indexOf(this);
×
427
        }
428

429
        /**
430
         * Returns true if the repeat index if the first one.
431
         *
432
         * @return true if the repeat index is 0, false otherwise
433
         */
434
        public boolean isFirst() {
435
            return getRepeatIndex() == 0;
×
436
        }
437

438
        /**
439
         * Returns true if the repeat index is the last one.
440
         *
441
         * @return true if the repeat index is the last one, false otherwise
442
         */
443
        public boolean isLast() {
444
            return getRepeatIndex() == repetitionGroups.size() - 1;
×
445
        }
446

447
        private void remove() {
448
            String thisSuffix = getRepeatSuffix();
×
449
            for (IRI iriBase : iriSet) {
×
450
                IRI thisIri = vf.createIRI(iriBase + thisSuffix);
×
451
                if (context.getComponentModels().containsKey(thisIri)) {
×
452
                    IModel swapModel1 = (IModel) context.getComponentModels().get(thisIri);
×
453
                    for (int i = getRepeatIndex() + 1; i < repetitionGroups.size(); i++) {
×
454
                        IModel swapModel2 = (IModel) context.getComponentModels().get(vf.createIRI(iriBase + getRepeatSuffix(i)));
×
455
                        if (swapModel1 != null && swapModel2 != null) {
×
456
                            // TODO check how to fix this -- maybe a function that does the swap?
457
                            swapModel1.setObject(swapModel2.getObject());
×
458
                        }
459
                        swapModel1 = swapModel2;
×
460
                    }
461
                    // Clear last object:
462
                    if (swapModel1 != null) {
×
463
                        // FIXME check if this is fine now
464
                        swapModel1.setObject(null);
×
465
                    }
466
                }
467
            }
×
468
            RepetitionGroup lastGroup = repetitionGroups.get(repetitionGroups.size() - 1);
×
469
            repetitionGroups.remove(lastGroup);
×
470
            for (ValueItem vi : lastGroup.items) {
×
471
                vi.removeFromContext();
×
472
            }
×
473
            repetitionGroupsChanged = true;
×
474
        }
×
475

476
        private String getRepeatSuffix() {
477
            return getRepeatSuffix(getRepeatIndex());
×
478
        }
479

480
        private String getRepeatSuffix(int i) {
481
            if (i == 0) return "";
×
482
            // TODO: Check that this double-underscore pattern isn't used otherwise:
483
            return "__" + i;
×
484
        }
485

486
        /**
487
         * Returns the template context associated.
488
         *
489
         * @return the TemplateContext
490
         */
491
        public TemplateContext getContext() {
492
            return context;
×
493
        }
494

495
        /**
496
         * Checks if this repetition group is optional.
497
         *
498
         * @return true if the repetition group is optional, false otherwise
499
         */
500
        public boolean isOptional() {
501
            if (!getTemplate().isOptionalStatement(statementId)) return false;
×
502
            if (repetitionGroups.size() == 0) return true;
×
503
            if (repetitionGroups.size() == 1 && repetitionGroups.get(0) == this) return true;
×
504
            return false;
×
505
        }
506

507
        private Value transform(Value value) {
508
            if (!(value instanceof IRI)) {
×
509
                return value;
×
510
            }
511
            IRI iri = (IRI) value;
×
512
            String iriString = iri.stringValue();
×
513
            iriString = iriString.replaceAll("~~ARTIFACTCODE~~", "~~~ARTIFACTCODE~~~");
×
514
            // Only add "__N" to URI from second repetition group on; for the first group, information about
515
            // narrow scopes is not yet complete.
516
            if (getRepeatIndex() > 0 && context.hasNarrowScope(iri)) {
×
517
                if (context.getTemplate().isPlaceholder(iri) || context.getTemplate().isLocalResource(iri)) {
×
518
                    iriString += getRepeatSuffix();
×
519
                }
520
            }
521
            return vf.createIRI(iriString);
×
522
        }
523

524
        /**
525
         * Adds the triples of this repetition group to the given NanopubCreator.
526
         *
527
         * @param npCreator the NanopubCreator to which the triples will be added
528
         * @throws org.nanopub.NanopubAlreadyFinalizedException if the NanopubCreator has already been finalized
529
         */
530
        public void addTriplesTo(NanopubCreator npCreator) throws NanopubAlreadyFinalizedException {
531
            Template t = getTemplate();
×
532
            for (IRI s : statementPartIds) {
×
533
                IRI subj = context.processIri((IRI) transform(t.getSubject(s)));
×
534
                IRI pred = context.processIri((IRI) transform(t.getPredicate(s)));
×
535
                Value obj = context.processValue(transform(t.getObject(s)));
×
536
                if (context.getType() == ContextType.ASSERTION) {
×
537
                    npCreator.addAssertionStatement(subj, pred, obj);
×
538
                } else if (context.getType() == ContextType.PROVENANCE) {
×
539
                    npCreator.addProvenanceStatement(subj, pred, obj);
×
540
                } else if (context.getType() == ContextType.PUBINFO) {
×
541
                    npCreator.addPubinfoStatement(subj, pred, obj);
×
542
                }
543
            }
×
544
            for (ValueItem vi : items) {
×
545
                if (vi.getComponent() instanceof GuidedChoiceItem) {
×
546
                    String value = ((GuidedChoiceItem) vi.getComponent()).getModel().getObject();
×
547
                    if (value != null && GuidedChoiceItem.getLabel(value) != null) {
×
548
                        String label = GuidedChoiceItem.getLabel(value);
×
549
                        if (label.length() > 1000) label = label.substring(0, 997) + "...";
×
550
                        try {
551
                            npCreator.addPubinfoStatement(vf.createIRI(value), NTEMPLATE.HAS_LABEL_FROM_API, vf.createLiteral(label));
×
552
                        } catch (IllegalArgumentException ex) {
×
553
                            logger.error("Could not create IRI from value: {}", value, ex);
×
554
                        }
×
555
                    }
556
                }
557
            }
×
558
        }
×
559

560
        private boolean hasEmptyElements() {
561
            for (IRI s : statementPartIds) {
×
562
                if (context.processIri((IRI) transform(getTemplate().getSubject(s))) == null) return true;
×
563
                if (context.processIri((IRI) transform(getTemplate().getPredicate(s))) == null) return true;
×
564
                if (context.processValue(transform(getTemplate().getObject(s))) == null) return true;
×
565
            }
×
566
            return false;
×
567
        }
568

569
        /**
570
         * Checks if this repetition group is empty, meaning it has no filled items.
571
         *
572
         * @return true if the repetition group is empty, false otherwise
573
         */
574
        public boolean isEmpty() {
575
            for (IRI s : statementPartIds) {
×
576
                Template t = getTemplate();
×
577
                IRI subj = t.getSubject(s);
×
578
                if (t.isPlaceholder(subj) && context.hasNarrowScope(subj) && context.processIri((IRI) transform(subj)) != null)
×
579
                    return false;
×
580
                IRI pred = t.getPredicate(s);
×
581
                if (t.isPlaceholder(pred) && context.hasNarrowScope(pred) && context.processIri((IRI) transform(pred)) != null)
×
582
                    return false;
×
583
                Value obj = t.getObject(s);
×
584
                if (obj instanceof IRI && t.isPlaceholder((IRI) obj) && context.hasNarrowScope((IRI) obj) && context.processValue(transform(obj)) != null)
×
585
                    return false;
×
586
            }
×
587
            return true;
×
588
        }
589

590
        /**
591
         * Checks if this repetition group matches the provided list of statements.
592
         *
593
         * @param statements the list of statements to match against
594
         * @return true if the repetition group matches, false otherwise
595
         */
596
        public boolean matches(List<Statement> statements) {
597
            if (filled) return false;
×
598
            List<Statement> st = new ArrayList<>(statements);
×
599
            for (StatementPartItem p : statementParts) {
×
600
                Statement matchedStatement = null;
×
601
                for (Statement s : st) {
×
602
                    if (
×
603
                            p.getPredicate().isUnifiableWith(s.getPredicate()) &&  // checking predicate first optimizes performance
×
604
                            p.getSubject().isUnifiableWith(s.getSubject()) &&
×
605
                            p.getObject().isUnifiableWith(s.getObject())) {
×
606
                        matchedStatement = s;
×
607
                        break;
×
608
                    }
609
                }
×
610
                if (matchedStatement == null) {
×
611
                    return false;
×
612
                } else {
613
                    st.remove(matchedStatement);
×
614
                }
615
            }
×
616
            return true;
×
617
        }
618

619
        /**
620
         * Fills this repetition group with the provided list of statements, unifying them with the statement parts.
621
         *
622
         * @param statements the list of statements to match against
623
         * @throws UnificationException if the statements cannot be unified with this repetition group
624
         */
625
        public void fill(List<Statement> statements) throws UnificationException {
626
            if (filled) throw new UnificationException("Already filled");
×
627
            for (StatementPartItem p : statementParts) {
×
628
                Statement matchedStatement = null;
×
629
                for (Statement s : statements) {
×
630
                    if (
×
631
                            p.getPredicate().isUnifiableWith(s.getPredicate()) &&  // checking predicate first optimizes performance
×
632
                            p.getSubject().isUnifiableWith(s.getSubject()) &&
×
633
                            p.getObject().isUnifiableWith(s.getObject())) {
×
634
                        p.getPredicate().unifyWith(s.getPredicate());
×
635
                        p.getSubject().unifyWith(s.getSubject());
×
636
                        p.getObject().unifyWith(s.getObject());
×
637
                        matchedStatement = s;
×
638
                        break;
×
639
                    }
640
                }
×
641
                if (matchedStatement == null) {
×
642
                    throw new UnificationException("Unification seemed to work but then didn't");
×
643
                } else {
644
                    statements.remove(matchedStatement);
×
645
                }
646
                filled = true;
×
647
            }
×
648
        }
×
649

650
        /**
651
         * Marks the filling of this repetition group as finished, indicating that all values have been filled.
652
         */
653
        public void fillFinished() {
654
            for (ValueItem vi : items) {
×
655
                vi.fillFinished();
×
656
            }
×
657
        }
×
658

659
        /**
660
         * Finalizes the values of all ValueItems in this repetition group.
661
         */
662
        public void finalizeValues() {
663
            for (ValueItem vi : items) {
×
664
                vi.finalizeValues();
×
665
            }
×
666
        }
×
667

668
    }
669

670
    private static final ValueFactory vf = SimpleValueFactory.getInstance();
×
671
    private static final List<Statement> dummyStatementList = new ArrayList<Statement>(Arrays.asList(vf.createStatement(vf.createIRI("http://dummy.com/"), vf.createIRI("http://dummy.com/"), vf.createIRI("http://dummy.com/"))));
×
672

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