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

knowledgepixels / nanodash / 18939026354

30 Oct 2025 11:24AM UTC coverage: 14.184% (-0.1%) from 14.315%
18939026354

push

github

ashleycaselli
Merge branch 'master' of github.com:knowledgepixels/nanodash

507 of 4504 branches covered (11.26%)

Branch coverage included in aggregate %.

1322 of 8391 relevant lines covered (15.75%)

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

3
import com.knowledgepixels.nanodash.LocalUri;
4
import com.knowledgepixels.nanodash.RestrictedChoice;
5
import com.knowledgepixels.nanodash.Utils;
6
import com.knowledgepixels.nanodash.template.Template;
7
import com.knowledgepixels.nanodash.template.TemplateContext;
8
import com.knowledgepixels.nanodash.template.UnificationException;
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.behavior.AttributeAppender;
13
import org.apache.wicket.markup.html.basic.Label;
14
import org.apache.wicket.markup.html.link.ExternalLink;
15
import org.apache.wicket.markup.html.panel.Panel;
16
import org.apache.wicket.model.IModel;
17
import org.apache.wicket.model.Model;
18
import org.apache.wicket.validation.IValidatable;
19
import org.apache.wicket.validation.IValidator;
20
import org.apache.wicket.validation.ValidationError;
21
import org.eclipse.rdf4j.model.IRI;
22
import org.eclipse.rdf4j.model.Value;
23
import org.eclipse.rdf4j.model.ValueFactory;
24
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
25
import org.slf4j.Logger;
26
import org.slf4j.LoggerFactory;
27
import org.wicketstuff.select2.ChoiceProvider;
28
import org.wicketstuff.select2.Response;
29
import org.wicketstuff.select2.Select2Choice;
30

31
import java.util.Collection;
32
import java.util.List;
33

34
/**
35
 * RestrictedChoiceItem is a Wicket component that provides a select2 choice input
36
 */
37
public class RestrictedChoiceItem extends AbstractContextComponent {
38

39
    private IRI iri;
40
    private Select2Choice<String> choice;
41
    private ExternalLink tooltipLink;
42
    private Label tooltipDescription;
43
    private IModel<String> model;
44
    private RestrictedChoice restrictedChoice;
45
    private static final Logger logger = LoggerFactory.getLogger(RestrictedChoiceItem.class);
×
46

47
    /**
48
     * Constructor for RestrictedChoiceItem.
49
     *
50
     * @param id       the component id
51
     * @param parentId the parent id (e.g., "subj" or "obj")
52
     * @param iri      the IRI of the restricted choice
53
     * @param optional whether the choice is optional
54
     * @param context  the template context
55
     */
56
    public RestrictedChoiceItem(String id, String parentId, IRI iri, boolean optional, final TemplateContext context) {
57
        super(id, context);
×
58
        this.iri = iri;
×
59
        Template template = context.getTemplate();
×
60
        model = (IModel<String>) context.getComponentModels().get(iri);
×
61
        if (model == null) {
×
62
            model = Model.of("");
×
63
            context.getComponentModels().put(iri, model);
×
64
        }
65
        String postfix = Utils.getUriPostfix(iri);
×
66
        if (context.hasParam(postfix)) {
×
67
            model.setObject(context.getParam(postfix));
×
68
        }
69
        restrictedChoice = new RestrictedChoice(iri, context);
×
70

71
        String prefixLabel = template.getPrefixLabel(iri);
×
72
        Label prefixLabelComp;
73
        if (prefixLabel == null) {
×
74
            prefixLabelComp = new Label("prefix", "");
×
75
            prefixLabelComp.setVisible(false);
×
76
        } else {
77
            if (!prefixLabel.isEmpty() && parentId.equals("subj") && !prefixLabel.matches("https?://.*")) {
×
78
                // Capitalize first letter of label if at subject position:
79
                prefixLabel = prefixLabel.substring(0, 1).toUpperCase() + prefixLabel.substring(1);
×
80
            }
81
            prefixLabelComp = new Label("prefix", prefixLabel);
×
82
        }
83
        add(prefixLabelComp);
×
84

85
        ChoiceProvider<String> choiceProvider = new ChoiceProvider<String>() {
×
86

87
            @Override
88
            public String getDisplayValue(String choiceId) {
89
                if (choiceId == null || choiceId.isEmpty()) return "";
×
90
                if (!choiceId.matches("https?://.+")) {
×
91
                    return choiceId;
×
92
                }
93
                String label = "";
×
94
                if (restrictedChoice.hasFixedPossibleValue(choiceId)) {
×
95
                    label = template.getLabel(vf.createIRI(choiceId));
×
96
                }
97
                if (label == null || label.isBlank()) {
×
98
                    return choiceId;
×
99
                }
100
                return label + " (" + choiceId + ")";
×
101
            }
102

103
            @Override
104
            public String getIdValue(String object) {
105
                return object;
×
106
            }
107

108
            // Getting strange errors with Tomcat if this method is not overridden:
109
            @Override
110
            public void detach() {
111
            }
×
112

113
            @Override
114
            public void query(String term, int page, Response<String> response) {
115
                List<String> possibleValues = restrictedChoice.getPossibleValues();
×
116

117
                if (term == null) {
×
118
                    response.addAll(possibleValues);
×
119
                    return;
×
120
                }
121
                term = term.toLowerCase();
×
122
                for (String s : possibleValues) {
×
123
                    if (s.toLowerCase().contains(term) || getDisplayValue(s).toLowerCase().contains(term))
×
124
                        response.add(s);
×
125
                }
×
126
            }
×
127

128
            @Override
129
            public Collection<String> toChoices(Collection<String> ids) {
130
                return ids;
×
131
            }
132

133
        };
134
        choice = new Select2Choice<String>("choice", model, choiceProvider);
×
135
        if (!optional) choice.setRequired(true);
×
136
        if (template.isLocalResource(iri)) {
×
137
            choice.add(new AttributeAppender("class", " short"));
×
138
        }
139
        choice.getSettings().setCloseOnSelect(true);
×
140
        String placeholder = template.getLabel(iri);
×
141
        if (placeholder == null) placeholder = "";
×
142
        choice.getSettings().setPlaceholder(placeholder);
×
143
        Utils.setSelect2ChoiceMinimalEscapeMarkup(choice);
×
144
        choice.getSettings().setAllowClear(true);
×
145
        choice.add(new ValueItem.KeepValueAfterRefreshBehavior());
×
146
        choice.add(new Validator());
×
147
        context.getComponents().add(choice);
×
148

149
        tooltipDescription = new Label("description", new IModel<String>() {
×
150

151
            @Override
152
            public String getObject() {
153
                String obj = RestrictedChoiceItem.this.getModel().getObject();
×
154
                if (obj == null || obj.isEmpty()) return "choose a value";
×
155
                String label = null;
×
156
                if (restrictedChoice.hasFixedPossibleValue(obj)) {
×
157
                    label = template.getLabel(vf.createIRI(obj));
×
158
                }
159
                if (label == null || !label.contains(" - ")) return "";
×
160
                return label.substring(label.indexOf(" - ") + 3);
×
161
            }
162

163
        });
164
        tooltipDescription.setOutputMarkupId(true);
×
165
        add(tooltipDescription);
×
166

167
        tooltipLink = Utils.getUriLink("uri", model);
×
168
        tooltipLink.setOutputMarkupId(true);
×
169
        add(tooltipLink);
×
170

171
        choice.add(new OnChangeAjaxBehavior() {
×
172

173
            @Override
174
            protected void onUpdate(AjaxRequestTarget target) {
175
                for (Component c : context.getComponents()) {
×
176
                    if (c == choice) continue;
×
177
                    if (c.getDefaultModel() == choice.getModel()) {
×
178
                        c.modelChanged();
×
179
                        target.add(c);
×
180
                    }
181
                }
×
182
                target.add(tooltipLink);
×
183
                target.add(tooltipDescription);
×
184
            }
×
185

186
        });
187
        add(choice);
×
188
    }
×
189

190
    /**
191
     * Get the model for this restricted choice item.
192
     *
193
     * @return the model containing the selected value
194
     */
195
    public IModel<String> getModel() {
196
        return model;
×
197
    }
198

199
    private static ValueFactory vf = SimpleValueFactory.getInstance();
×
200

201
    /**
202
     * {@inheritDoc}
203
     */
204
    @Override
205
    public void removeFromContext() {
206
        context.getComponents().remove(choice);
×
207
    }
×
208

209
    /**
210
     * {@inheritDoc}
211
     */
212
    @Override
213
    public boolean isUnifiableWith(Value v) {
214
        if (v == null) return true;
×
215
        if (v instanceof IRI) {
×
216
            String vs = v.stringValue();
×
217
            if (Utils.isLocalURI(vs)) vs = vs.replaceFirst("^" + LocalUri.PREFIX, "");
×
218
            if (!restrictedChoice.hasPossibleRefValues() && !restrictedChoice.hasFixedPossibleValue(vs)) {
×
219
                return false;
×
220
            }
221
            if (choice.getModelObject().isEmpty()) {
×
222
                return true;
×
223
            }
224
            return vs.equals(choice.getModelObject());
×
225
        }
226
        return false;
×
227
    }
228

229
    /**
230
     * {@inheritDoc}
231
     */
232
    @Override
233
    public void unifyWith(Value v) throws UnificationException {
234
        if (v == null) return;
×
235
        String vs = v.stringValue();
×
236
        if (Utils.isLocalURI(vs)) vs = vs.replaceFirst("^" + LocalUri.PREFIX, "");
×
237
        if (!isUnifiableWith(v)) throw new UnificationException(vs);
×
238
        choice.setModelObject(vs);
×
239
    }
×
240

241
    /**
242
     * {@inheritDoc}
243
     */
244
    @Override
245
    public void fillFinished() {
246
    }
×
247

248
    /**
249
     * {@inheritDoc}
250
     */
251
    @Override
252
    public void finalizeValues() {
253
        Value defaultValue = context.getTemplate().getDefault(iri);
×
254
        if (isUnifiableWith(defaultValue)) {
×
255
            try {
256
                unifyWith(defaultValue);
×
257
            } catch (UnificationException ex) {
×
258
                logger.error("Could not unify with default value: {}", defaultValue, ex);
×
259
            }
×
260
        }
261
    }
×
262

263
    /**
264
     * <p>toString.</p>
265
     *
266
     * @return a {@link java.lang.String} object
267
     */
268
    public String toString() {
269
        return "[Restricted choice item: " + iri + "]";
×
270
    }
271

272

273
    /**
274
     * Validator for the restricted choice item.
275
     */
276
    protected class Validator extends InvalidityHighlighting implements IValidator<String> {
277

278
        /**
279
         * Default constructor.
280
         */
281
        public Validator() {
×
282
        }
×
283

284
        @Override
285
        public void validate(IValidatable<String> s) {
286
            if (!restrictedChoice.getPossibleValues().contains(s.getValue())) {
×
287
                s.error(new ValidationError("Invalid choice"));
×
288
            }
289
        }
×
290

291
    }
292

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