• 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

25.16
src/main/java/com/knowledgepixels/nanodash/component/LiteralTextfieldItem.java
1
package com.knowledgepixels.nanodash.component;
2

3
import com.knowledgepixels.nanodash.Utils;
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.Component;
9
import org.apache.wicket.ajax.AjaxRequestTarget;
10
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
11
import org.apache.wicket.markup.html.basic.Label;
12
import org.apache.wicket.markup.html.form.AbstractTextComponent;
13
import org.apache.wicket.markup.html.form.TextField;
14
import org.apache.wicket.model.IModel;
15
import org.apache.wicket.model.Model;
16
import org.apache.wicket.validation.IValidator;
17
import org.apache.wicket.validation.ValidationError;
18
import org.eclipse.rdf4j.model.IRI;
19
import org.eclipse.rdf4j.model.Literal;
20
import org.eclipse.rdf4j.model.Value;
21
import org.eclipse.rdf4j.model.util.Literals;
22
import org.eclipse.rdf4j.model.vocabulary.XSD;
23
import org.slf4j.Logger;
24
import org.slf4j.LoggerFactory;
25

26
/**
27
 * A component that represents a text field for entering literal values.
28
 */
29
public class LiteralTextfieldItem extends AbstractContextComponent {
30

31
    private AbstractTextComponent<String> textfield;
32
    private Label languageComp, datatypeComp;
33
    private IModel<String> languageModel, datatypeModel;
34
    private final String regex;
35
    private final IRI iri;
36
    private final static Logger logger = LoggerFactory.getLogger(LiteralTextfieldItem.class);
12✔
37

38
    /**
39
     * Constructs a LiteralTextfieldItem with the specified ID, IRI, optional flag, and template context.
40
     *
41
     * @param id       the component ID
42
     * @param iri      the IRI associated with this text field
43
     * @param optional whether this field is optional
44
     * @param context  the template context containing models and parameters
45
     */
46
    public LiteralTextfieldItem(String id, final IRI iri, boolean optional, TemplateContext context) {
47
        super(id, context);
12✔
48
        final Template template = context.getTemplate();
9✔
49
        this.iri = iri;
9✔
50
        regex = template.getRegex(iri);
15✔
51
        IModel<String> model = (IModel<String>) context.getComponentModels().get(iri);
18✔
52
        boolean modelIsNew = false;
6✔
53
        if (model == null) {
6!
54
            model = Model.of("");
×
55
            context.getComponentModels().put(iri, model);
×
56
            modelIsNew = true;
×
57
        }
58
        String postfix = Utils.getUriPostfix(iri);
9✔
59
        if (modelIsNew && context.hasParam(postfix)) {
6!
60
            model.setObject(context.getParam(postfix));
×
61
        }
62
        AbstractTextComponent<String> tc = initTextComponent(model);
12✔
63
        if (!optional) tc.setRequired(true);
18!
64
        if (context.getTemplate().getLabel(iri) != null) {
15!
65
            tc.add(new AttributeModifier("placeholder", context.getTemplate().getLabel(iri)));
×
66
        }
67
        tc.add((IValidator<String>) s -> {
15✔
68
            if (regex != null) {
×
69
                if (!s.getValue().matches(regex)) {
×
70
                    s.error(new ValidationError("Value '" + s.getValue() + "' doesn't match the pattern '" + regex + "'"));
×
71
                }
72
            }
73
        });
×
74

75
        tc.add(new OnChangeAjaxBehavior() {
78✔
76
            @Override
77
            protected void onUpdate(AjaxRequestTarget target) {
78
                for (Component c : context.getComponents()) {
×
79
                    if (c == tc) continue;
×
80
                    if (c.getDefaultModel() == tc.getModel()) {
×
81
                        c.modelChanged();
×
82
                        target.add(c);
×
83
                    }
84
                }
×
85
            }
×
86
        });
87
        context.getComponentModels().put(iri, tc.getModel());
21✔
88
        context.getComponents().add(tc);
15✔
89
        tc.add(new ValueItem.KeepValueAfterRefreshBehavior());
33✔
90
        tc.add(new InvalidityHighlighting());
33✔
91
        add(tc);
27✔
92

93
        languageModel = Model.of("");
12✔
94
        languageComp = new Label("language", languageModel);
24✔
95
        datatypeModel = Model.of("");
12✔
96
        datatypeComp = new Label("datatype", datatypeModel);
24✔
97
        if (template.getLanguageTag(iri) != null) {
12!
98
            languageModel.setObject("(" + template.getLanguageTag(iri) + ")");
×
99
            datatypeComp.setVisible(false);
×
100
        } else if (template.getDatatype(iri) != null && !template.getDatatype(iri).equals(XSD.STRING)) {
12!
101
            datatypeModel.setObject("(" + template.getDatatype(iri).stringValue().replace(XSD.NAMESPACE, "xsd:") + ")");
×
102
            languageComp.setVisible(false);
×
103
        } else {
104
            datatypeComp.setVisible(false);
15✔
105
            languageComp.setVisible(false);
15✔
106
        }
107
        add(languageComp);
30✔
108
        add(datatypeComp);
30✔
109
    }
3✔
110

111
    /**
112
     * <p>initTextComponent.</p>
113
     *
114
     * @param model a {@link org.apache.wicket.model.IModel} object
115
     * @return a {@link org.apache.wicket.markup.html.form.AbstractTextComponent} object
116
     */
117
    protected AbstractTextComponent<String> initTextComponent(IModel<String> model) {
118
        textfield = new TextField<>("textfield", model);
21✔
119
        return textfield;
9✔
120
    }
121

122
    /**
123
     * <p>getTextComponent.</p>
124
     *
125
     * @return a {@link org.apache.wicket.markup.html.form.AbstractTextComponent} object
126
     */
127
    protected AbstractTextComponent<String> getTextComponent() {
128
        return textfield;
×
129
    }
130

131
    /**
132
     * {@inheritDoc}
133
     */
134
    @Override
135
    public void removeFromContext() {
136
        context.getComponents().remove(getTextComponent());
×
137
    }
×
138

139
    /**
140
     * {@inheritDoc}
141
     */
142
    @Override
143
    public boolean isUnifiableWith(Value v) {
144
        if (v == null) return true;
×
145
        if (v instanceof Literal vL) {
×
146
            if (regex != null && !vL.stringValue().matches(regex)) {
×
147
                return false;
×
148
            }
149
            if (getTextComponent().getModelObject() == null || getTextComponent().getModelObject().isEmpty()) {
×
150
                return true;
×
151
            }
152
            String languagetag = context.getTemplate().getLanguageTag(iri);
×
153
            IRI datatype = context.getTemplate().getDatatype(iri);
×
154
            if (languagetag != null) {
×
155
                if (!vL.getLanguage().isPresent() || !Literals.normalizeLanguageTag(vL.getLanguage().get()).equals(languagetag)) {
×
156
                    return false;
×
157
                }
158
            } else if (datatype != null) {
×
159
                if (!vL.getDatatype().equals(datatype)) {
×
160
                    return false;
×
161
                }
162
            }
163
            return vL.stringValue().equals(getTextComponent().getModelObject());
×
164
        }
165
        return false;
×
166
    }
167

168
    /**
169
     * {@inheritDoc}
170
     */
171
    @Override
172
    public void unifyWith(Value v) throws UnificationException {
173
        if (v == null) return;
×
174
        if (!isUnifiableWith(v)) throw new UnificationException(v.stringValue());
×
175
        Literal vL = (Literal) v;
×
176
        getTextComponent().setModelObject(vL.stringValue());
×
177
        if (context.getTemplate().getLanguageTag(iri) == null && vL.getLanguage().isPresent()) {
×
178
            languageModel.setObject("(" + vL.getLanguage().get().toLowerCase() + ")");
×
179
            languageComp.setVisible(true);
×
180
        } else if (context.getTemplate().getDatatype(iri) == null && !vL.getDatatype().equals(XSD.STRING)) {
×
181
            datatypeModel.setObject("(" + vL.getDatatype().stringValue().replace(XSD.NAMESPACE, "xsd:") + ")");
×
182
            datatypeComp.setVisible(true);
×
183
        }
184

185
        getTextComponent().setModelObject(v.stringValue());
×
186
    }
×
187

188
    /**
189
     * {@inheritDoc}
190
     */
191
    @Override
192
    public void fillFinished() {
193
    }
×
194

195
    /**
196
     * {@inheritDoc}
197
     */
198
    @Override
199
    public void finalizeValues() {
200
        Value defaultValue = context.getTemplate().getDefault(iri);
×
201
        if (isUnifiableWith(defaultValue)) {
×
202
            try {
203
                unifyWith(defaultValue);
×
204
            } catch (UnificationException ex) {
×
205
                logger.error("Could not unify with default value.", ex);
×
206
            }
×
207
        }
208
    }
×
209

210
    /**
211
     * {@inheritDoc}
212
     */
213
    @Override
214
    public String toString() {
215
        return "[Literal textfield item]";
×
216
    }
217

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