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

knowledgepixels / nanodash / 25678638590

11 May 2026 03:08PM UTC coverage: 20.512% (+2.2%) from 18.296%
25678638590

push

github

web-flow
Merge pull request #455 from knowledgepixels/fix-repetition-resets-edited-values

fix: don't reseed shared model from URL param on repetition (#271)

1013 of 6236 branches covered (16.24%)

Branch coverage included in aggregate %.

2592 of 11339 relevant lines covered (22.86%)

3.28 hits per line

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

16.67
src/main/java/com/knowledgepixels/nanodash/component/ValueTextfieldItem.java
1
package com.knowledgepixels.nanodash.component;
2

3
import com.knowledgepixels.nanodash.LocalUri;
4
import com.knowledgepixels.nanodash.Utils;
5
import com.knowledgepixels.nanodash.template.Template;
6
import com.knowledgepixels.nanodash.template.TemplateContext;
7
import com.knowledgepixels.nanodash.template.UnificationException;
8
import org.apache.wicket.AttributeModifier;
9
import org.apache.wicket.Component;
10
import org.apache.wicket.ajax.AjaxRequestTarget;
11
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
12
import org.apache.wicket.markup.html.form.TextField;
13
import org.apache.wicket.model.IModel;
14
import org.apache.wicket.model.Model;
15
import org.apache.wicket.validation.IValidatable;
16
import org.apache.wicket.validation.IValidator;
17
import org.apache.wicket.validation.Validatable;
18
import org.apache.wicket.validation.ValidationError;
19
import org.eclipse.rdf4j.common.net.ParsedIRI;
20
import org.eclipse.rdf4j.model.IRI;
21
import org.eclipse.rdf4j.model.Literal;
22
import org.eclipse.rdf4j.model.Value;
23
import org.slf4j.Logger;
24
import org.slf4j.LoggerFactory;
25

26
import java.net.URISyntaxException;
27

28
/**
29
 * A text field component for entering values in a template.
30
 */
31
public class ValueTextfieldItem extends AbstractContextComponent {
32

33
    private TextField<String> textfield;
34
    private IRI iri;
35
    private static final Logger logger = LoggerFactory.getLogger(ValueTextfieldItem.class);
12✔
36

37
    /**
38
     * Constructor for creating a text field item.
39
     *
40
     * @param id       the component ID
41
     * @param parentId the parent component ID
42
     * @param iriP     the IRI associated with this text field
43
     * @param optional whether the field is optional
44
     * @param context  the template context containing models and components
45
     */
46
    public ValueTextfieldItem(String id, String parentId, final IRI iriP, boolean optional, final TemplateContext context) {
47
        super(id, context);
12✔
48
        this.iri = iriP;
9✔
49
        final Template template = context.getTemplate();
9✔
50
        IModel<String> model = (IModel<String>) context.getComponentModels().get(iri);
21✔
51
        boolean modelIsNew = false;
6✔
52
        if (model == null) {
6!
53
            model = Model.of("");
×
54
            context.getComponentModels().put(iri, model);
×
55
            modelIsNew = true;
×
56
        }
57
        String postfix = Utils.getUriPostfix(iri);
12✔
58
        if (modelIsNew && context.hasParam(postfix)) {
6!
59
            model.setObject(context.getParam(postfix));
×
60
        }
61
        textfield = new TextField<>("textfield", model);
21✔
62
        if (!optional) textfield.setRequired(true);
21!
63
        textfield.add(new Validator(iri, template));
30✔
64
        context.getComponents().add(textfield);
18✔
65
        if (template.getLabel(iri) != null) {
15!
66
            textfield.add(new AttributeModifier("placeholder", template.getLabel(iri)));
×
67
            textfield.setLabel(Model.of(template.getLabel(iri)));
×
68
        }
69
        textfield.add(new OnChangeAjaxBehavior() {
69✔
70

71
            @Override
72
            protected void onUpdate(AjaxRequestTarget target) {
73
                for (Component c : context.getComponents()) {
×
74
                    if (c == textfield) continue;
×
75
                    if (c.getDefaultModel() == textfield.getModel()) {
×
76
                        c.modelChanged();
×
77
                        target.add(c);
×
78
                    }
79
                }
×
80
            }
×
81

82
        });
83
        add(textfield);
30✔
84
    }
3✔
85

86
    /**
87
     * {@inheritDoc}
88
     */
89
    @Override
90
    public void removeFromContext() {
91
        context.getComponents().remove(textfield);
×
92
    }
×
93

94
    /**
95
     * {@inheritDoc}
96
     */
97
    @Override
98
    public boolean isUnifiableWith(Value v) {
99
        if (v == null) return true;
×
100
        String vs = v.stringValue();
×
101
        if (v instanceof Literal vL) vs = Utils.getSerializedLiteral(vL);
×
102
        if (Utils.isLocalURI(vs)) vs = vs.replaceFirst("^" + LocalUri.PREFIX, "");
×
103
        Validatable<String> validatable = new Validatable<>(vs);
×
104
        if (v instanceof IRI && context.getTemplate().isLocalResource(iri) && !Utils.isUriPostfix(vs)) {
×
105
            vs = Utils.getUriPostfix(vs);
×
106
        }
107
        new Validator(iri, context.getTemplate()).validate(validatable);
×
108
        if (!validatable.isValid()) {
×
109
            return false;
×
110
        }
111
        if (textfield.getModelObject() == null || textfield.getModelObject().isEmpty()) {
×
112
            return true;
×
113
        }
114
        return vs.equals(textfield.getModelObject());
×
115
    }
116

117
    /**
118
     * {@inheritDoc}
119
     */
120
    @Override
121
    public void unifyWith(Value v) throws UnificationException {
122
        if (v == null) return;
×
123
        if (!isUnifiableWith(v)) throw new UnificationException(v.stringValue());
×
124
        String vs = v.stringValue();
×
125
        if (Utils.isLocalURI(vs)) {
×
126
            textfield.setModelObject(vs.replaceFirst("^" + LocalUri.PREFIX, ""));
×
127
        } else if (v instanceof Literal vL) {
×
128
            textfield.setModelObject(Utils.getSerializedLiteral(vL));
×
129
        } else {
130
            textfield.setModelObject(vs);
×
131
        }
132
    }
×
133

134

135
    /**
136
     * Validator class for validating the text field input.
137
     */
138
    protected static class Validator extends InvalidityHighlighting implements IValidator<String> {
139

140
//                private IRI iri;
141
//                private Template template;
142

143
        /**
144
         * Constructor for the validator.
145
         *
146
         * @param iri      the IRI associated with the value
147
         * @param template the template containing the context
148
         */
149
        public Validator(IRI iri, Template template) {
6✔
150
//                        this.iri = iri;
151
//                        this.template = template;
152
        }
3✔
153

154
        @Override
155
        public void validate(IValidatable<String> s) {
156
            if (s.getValue().startsWith("\"")) {
×
157
                if (!Utils.isValidLiteralSerialization(s.getValue())) {
×
158
                    s.error(new ValidationError("Invalid literal value"));
×
159
                }
160
                return;
×
161
            }
162
            String p = "";
×
163
            if (s.getValue().matches("[^:# ]+")) p = LocalUri.PREFIX;
×
164
            try {
165
                ParsedIRI piri = new ParsedIRI(p + s.getValue());
×
166
                if (!piri.isAbsolute()) {
×
167
                    s.error(new ValidationError("IRI not well-formed"));
×
168
                }
169
                if (p.isEmpty() && !Utils.isLocalURI(s.getValue()) && !(s.getValue()).matches("https?://.+")) {
×
170
                    s.error(new ValidationError("Only http(s):// IRIs are allowed here"));
×
171
                }
172
            } catch (URISyntaxException ex) {
×
173
                s.error(new ValidationError("IRI not well-formed"));
×
174
            }
×
175
        }
×
176

177
    }
178

179
    /**
180
     * {@inheritDoc}
181
     */
182
    @Override
183
    public void fillFinished() {
184
    }
×
185

186
    /**
187
     * {@inheritDoc}
188
     */
189
    @Override
190
    public void finalizeValues() {
191
        Value defaultValue = context.getTemplate().getDefault(iri);
×
192
        if (isUnifiableWith(defaultValue)) {
×
193
            try {
194
                unifyWith(defaultValue);
×
195
            } catch (UnificationException ex) {
×
196
                logger.error("Unification with default value failed: {}", ex.getMessage());
×
197
            }
×
198
        }
199
    }
×
200

201
    /**
202
     * <p>toString.</p>
203
     *
204
     * @return a {@link java.lang.String} object
205
     */
206
    public String toString() {
207
        return "[value textfield item: " + iri + "]";
×
208
    }
209

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