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

knowledgepixels / nanodash / 19032518047

03 Nov 2025 11:10AM UTC coverage: 14.338% (-0.9%) from 15.251%
19032518047

push

github

web-flow
Merge pull request #269 from knowledgepixels/245-local-uri-without-slashes-or-hashes

Add check for local URIs to ensure that they don't contain slashes or hashes

518 of 4518 branches covered (11.47%)

Branch coverage included in aggregate %.

1333 of 8392 relevant lines covered (15.88%)

0.71 hits per line

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

33.54
src/main/java/com/knowledgepixels/nanodash/template/ValueFiller.java
1
package com.knowledgepixels.nanodash.template;
2

3
import com.knowledgepixels.nanodash.LocalUri;
4
import com.knowledgepixels.nanodash.Utils;
5
import com.knowledgepixels.nanodash.component.GuidedChoiceItem;
6
import com.knowledgepixels.nanodash.component.PublishForm.FillMode;
7
import org.eclipse.rdf4j.model.*;
8
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
9
import org.eclipse.rdf4j.model.vocabulary.DCTERMS;
10
import org.eclipse.rdf4j.model.vocabulary.RDFS;
11
import org.nanopub.Nanopub;
12
import org.nanopub.vocabulary.NPX;
13
import org.nanopub.vocabulary.NTEMPLATE;
14
import org.slf4j.Logger;
15
import org.slf4j.LoggerFactory;
16

17
import java.util.ArrayList;
18
import java.util.List;
19
import java.util.Set;
20

21
/**
22
 * ValueFiller is a utility class that processes a Nanopub and fills a TemplateContext.
23
 */
24
public class ValueFiller {
25

26
    private static ValueFactory vf = SimpleValueFactory.getInstance();
2✔
27

28
    private Nanopub fillNp;
29
    private FillMode fillMode;
30
    private List<Statement> unusedStatements = new ArrayList<>();
5✔
31
    private int initialSize;
32
    private boolean formMode;
33
    private static final Logger logger = LoggerFactory.getLogger(ValueFiller.class);
4✔
34

35
    /**
36
     * Constructor for ValueFiller.
37
     *
38
     * @param fillNp      the Nanopub to fill
39
     * @param contextType the type of context to fill
40
     * @param formMode    if true, the filler will adapt to form mode, filtering out certain statements
41
     */
42
    public ValueFiller(Nanopub fillNp, ContextType contextType, boolean formMode) {
43
        this(fillNp, contextType, formMode, null);
6✔
44
    }
1✔
45

46
    /**
47
     * Constructor for ValueFiller with specified fill mode.
48
     *
49
     * @param fillNp      the Nanopub to fill
50
     * @param contextType the type of context to fill
51
     * @param formMode    if true, the filler will adapt to form mode, filtering out certain statements
52
     * @param fillMode    the fill mode to use, can be null for default behavior
53
     */
54
    public ValueFiller(Nanopub fillNp, ContextType contextType, boolean formMode, FillMode fillMode) {
2✔
55
        this.fillNp = fillNp;
3✔
56
        this.formMode = formMode;
3✔
57
        this.fillMode = fillMode;
3✔
58
        Set<Statement> statements;
59
        if (contextType == ContextType.ASSERTION) {
3!
60
            statements = fillNp.getAssertion();
4✔
61
        } else if (contextType == ContextType.PROVENANCE) {
×
62
            statements = fillNp.getProvenance();
×
63
        } else {
64
            statements = fillNp.getPubinfo();
×
65
        }
66
        for (Statement st : statements) {
10✔
67
            Statement stT = transform(st);
4✔
68
            if (stT != null) unusedStatements.add(stT);
7!
69
        }
1✔
70
        unusedStatements.sort((st1, st2) -> {
4✔
71
            String st1s = st1.getSubject() + " " + st1.getPredicate() + " " + st1.getObject();
×
72
            String st2s = st2.getSubject() + " " + st2.getPredicate() + " " + st2.getObject();
×
73
            return st1s.compareTo(st2s);
×
74
        });
75
        initialSize = unusedStatements.size();
5✔
76
    }
1✔
77

78
    /**
79
     * Fills the TemplateContext with the unused statements.
80
     *
81
     * @param context the TemplateContext to fill
82
     */
83
    public void fill(TemplateContext context) {
84
        try {
85
            context.fill(unusedStatements);
×
86
        } catch (UnificationException ex) {
×
87
            logger.error("Could not fill template context", ex);
×
88
        }
×
89
    }
×
90

91
    /**
92
     * Checks if the Nanopub has any statements.
93
     *
94
     * @return true if there are statements, false otherwise
95
     */
96
    public boolean hasStatements() {
97
        return initialSize > 0;
6!
98
    }
99

100
    /**
101
     * Checks if there are any used statements in the Nanopub.
102
     *
103
     * @return true if there are used statements, false otherwise
104
     */
105
    public boolean hasUsedStatements() {
106
        return unusedStatements.size() < initialSize;
8!
107
    }
108

109
    /**
110
     * Checks if there are any unused statements in the Nanopub.
111
     *
112
     * @return true if there are unused statements, false otherwise
113
     */
114
    public boolean hasUnusedStatements() {
115
        return !unusedStatements.isEmpty();
7!
116
    }
117

118
    /**
119
     * Returns the list of unused statements in the Nanopub.
120
     *
121
     * @return the list of unused statements
122
     */
123
    public List<Statement> getUnusedStatements() {
124
        return unusedStatements;
3✔
125
    }
126

127
    /**
128
     * Removes a specific unused statement from the list.
129
     *
130
     * @param st the statement to remove
131
     */
132
    public void removeUnusedStatement(Statement st) {
133
        unusedStatements.remove(st);
×
134
    }
×
135

136
    /**
137
     * Removes unused statements based on the specified subject, predicate, and object.
138
     *
139
     * @param subj the subject to match, can be null
140
     * @param pred the predicate to match, can be null
141
     * @param obj  the object to match, can be null
142
     */
143
    public void removeUnusedStatements(IRI subj, IRI pred, Value obj) {
144
        for (Statement st : new ArrayList<>(unusedStatements)) {
×
145
            if (subj != null && !st.getSubject().equals(subj)) continue;
×
146
            if (pred != null && !st.getPredicate().equals(pred)) continue;
×
147
            if (obj != null && !st.getObject().equals(obj)) continue;
×
148
            unusedStatements.remove(st);
×
149
        }
×
150
    }
×
151

152
    Statement transform(Statement st) {
153
        if (formMode && st.getContext().equals(fillNp.getPubinfoUri())) {
10!
154
            IRI pred = st.getPredicate();
×
155
            // TODO We might want to filter some of these out afterwards in PublishForm, to be more precise:
156
            if (st.getSubject().equals(fillNp.getUri())) {
×
157
                if (pred.equals(DCTERMS.CREATED)) return null;
×
158
                if (pred.equals(NPX.SUPERSEDES)) return null;
×
159
                if (pred.equals(RDFS.LABEL)) return null;
×
160
                if (pred.equals(NPX.INTRODUCES)) return null;
×
161
                if (pred.equals(NPX.EMBEDS)) return null;
×
162
                if (pred.equals(NPX.WAS_CREATED_AT)) return null;
×
163
                if (pred.equals(NTEMPLATE.WAS_CREATED_FROM_TEMPLATE)) return null;
×
164
                if (pred.equals(NTEMPLATE.WAS_CREATED_FROM_PROVENANCE_TEMPLATE)) return null;
×
165
                if (pred.equals(NTEMPLATE.WAS_CREATED_FROM_PUBINFO_TEMPLATE)) return null;
×
166
            }
167
            if (pred.equals(NPX.HAS_ALGORITHM)) return null;
×
168
            if (pred.equals(NPX.HAS_PUBLIC_KEY)) return null;
×
169
            if (pred.equals(NPX.HAS_SIGNATURE)) return null;
×
170
            if (pred.equals(NPX.HAS_SIGNATURE_TARGET)) return null;
×
171
            if (pred.equals(NPX.SIGNED_BY)) return null;
×
172
            if (pred.equals(NTEMPLATE.HAS_LABEL_FROM_API)) {
×
173
                GuidedChoiceItem.setLabel(st.getSubject().stringValue(), st.getObject().stringValue());
×
174
                return null;
×
175
            }
176
            if (pred.equals(RDFS.LABEL)) {
×
177
                GuidedChoiceItem.setLabel(st.getSubject().stringValue(), st.getObject().stringValue());
×
178
            }
179
        }
180
        return vf.createStatement(
5✔
181
                (Resource) transform(st.getSubject()),
5✔
182
                (IRI) transform(st.getPredicate()),
5✔
183
                transform(st.getObject()),
4✔
184
                (Resource) transform(st.getContext()));
3✔
185
    }
186

187
    Value transform(Value v) {
188
        if (fillNp.getUri().equals(v)) {
6✔
189
            return LocalUri.of("nanopub");
3✔
190
        } else if (fillNp.getAssertionUri().equals(v)) {
6✔
191
            return LocalUri.of("assertion");
3✔
192
        } else if (v instanceof IRI iri && formMode) {
9!
193
            if (!Utils.getIntroducedIriIds(fillNp).contains(iri.stringValue()) || fillMode != FillMode.SUPERSEDE) {
7!
194
                if (v.stringValue().startsWith(fillNp.getUri().stringValue())) {
8!
195
                    return LocalUri.of(Utils.getUriPostfix(v.stringValue()));
×
196
                }
197
            }
198
        }
199
        return v;
2✔
200
    }
201

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