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

knowledgepixels / nanodash / 17380144000

01 Sep 2025 02:12PM UTC coverage: 12.03% (+0.05%) from 11.978%
17380144000

push

github

ashleycaselli
refactor: replace printStackTrace with logger.error for better error handling

330 of 3850 branches covered (8.57%)

Branch coverage included in aggregate %.

958 of 6857 relevant lines covered (13.97%)

0.62 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.RestrictedChoice;
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.Component;
9
import org.apache.wicket.ajax.AjaxRequestTarget;
10
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
11
import org.apache.wicket.behavior.AttributeAppender;
12
import org.apache.wicket.markup.html.basic.Label;
13
import org.apache.wicket.markup.html.link.ExternalLink;
14
import org.apache.wicket.markup.html.panel.Panel;
15
import org.apache.wicket.model.IModel;
16
import org.apache.wicket.model.Model;
17
import org.apache.wicket.validation.IValidatable;
18
import org.apache.wicket.validation.IValidator;
19
import org.apache.wicket.validation.ValidationError;
20
import org.eclipse.rdf4j.model.IRI;
21
import org.eclipse.rdf4j.model.Value;
22
import org.eclipse.rdf4j.model.ValueFactory;
23
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
24
import org.slf4j.Logger;
25
import org.slf4j.LoggerFactory;
26
import org.wicketstuff.select2.ChoiceProvider;
27
import org.wicketstuff.select2.Response;
28
import org.wicketstuff.select2.Select2Choice;
29

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

33
/**
34
 * RestrictedChoiceItem is a Wicket component that provides a select2 choice input
35
 */
36
public class RestrictedChoiceItem extends Panel implements ContextComponent {
37

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

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

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

87
        ChoiceProvider<String> choiceProvider = new ChoiceProvider<String>() {
×
88

89
            private static final long serialVersionUID = 1L;
90

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

107
            @Override
108
            public String getIdValue(String object) {
109
                return object;
×
110
            }
111

112
            // Getting strange errors with Tomcat if this method is not overridden:
113
            @Override
114
            public void detach() {
115
            }
×
116

117
            @Override
118
            public void query(String term, int page, Response<String> response) {
119
                List<String> possibleValues = restrictedChoice.getPossibleValues();
×
120

121
                if (term == null) {
×
122
                    response.addAll(possibleValues);
×
123
                    return;
×
124
                }
125
                term = term.toLowerCase();
×
126
                for (String s : possibleValues) {
×
127
                    if (s.toLowerCase().contains(term) || getDisplayValue(s).toLowerCase().contains(term))
×
128
                        response.add(s);
×
129
                }
×
130
            }
×
131

132
            @Override
133
            public Collection<String> toChoices(Collection<String> ids) {
134
                return ids;
×
135
            }
136

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

153
        tooltipDescription = new Label("description", new IModel<String>() {
×
154

155
            private static final long serialVersionUID = 1L;
156

157
            @Override
158
            public String getObject() {
159
                String obj = RestrictedChoiceItem.this.getModel().getObject();
×
160
                if (obj == null || obj.isEmpty()) return "choose a value";
×
161
                String label = null;
×
162
                if (restrictedChoice.hasFixedPossibleValue(obj)) {
×
163
                    label = template.getLabel(vf.createIRI(obj));
×
164
                }
165
                if (label == null || !label.contains(" - ")) return "";
×
166
                return label.substring(label.indexOf(" - ") + 3);
×
167
            }
168

169
        });
170
        tooltipDescription.setOutputMarkupId(true);
×
171
        add(tooltipDescription);
×
172

173
        tooltipLink = Utils.getUriLink("uri", model);
×
174
        tooltipLink.setOutputMarkupId(true);
×
175
        add(tooltipLink);
×
176

177
        choice.add(new OnChangeAjaxBehavior() {
×
178

179
            private static final long serialVersionUID = 1L;
180

181
            @Override
182
            protected void onUpdate(AjaxRequestTarget target) {
183
                for (Component c : context.getComponents()) {
×
184
                    if (c == choice) continue;
×
185
                    if (c.getDefaultModel() == choice.getModel()) {
×
186
                        c.modelChanged();
×
187
                        target.add(c);
×
188
                    }
189
                }
×
190
                target.add(tooltipLink);
×
191
                target.add(tooltipDescription);
×
192
            }
×
193

194
        });
195
        add(choice);
×
196
    }
×
197

198
    /**
199
     * Get the model for this restricted choice item.
200
     *
201
     * @return the model containing the selected value
202
     */
203
    public IModel<String> getModel() {
204
        return model;
×
205
    }
206

207
    private static ValueFactory vf = SimpleValueFactory.getInstance();
×
208

209
    /**
210
     * {@inheritDoc}
211
     */
212
    @Override
213
    public void removeFromContext() {
214
        context.getComponents().remove(choice);
×
215
    }
×
216

217
    /**
218
     * {@inheritDoc}
219
     */
220
    @Override
221
    public boolean isUnifiableWith(Value v) {
222
        if (v == null) return true;
×
223
        if (v instanceof IRI) {
×
224
            String vs = v.stringValue();
×
225
            if (vs.startsWith("local:")) vs = vs.replaceFirst("^local:", "");
×
226
            if (!restrictedChoice.hasPossibleRefValues() && !restrictedChoice.hasFixedPossibleValue(vs)) {
×
227
                return false;
×
228
            }
229
            if (choice.getModelObject().isEmpty()) {
×
230
                return true;
×
231
            }
232
            return vs.equals(choice.getModelObject());
×
233
        }
234
        return false;
×
235
    }
236

237
    /**
238
     * {@inheritDoc}
239
     */
240
    @Override
241
    public void unifyWith(Value v) throws UnificationException {
242
        if (v == null) return;
×
243
        String vs = v.stringValue();
×
244
        if (vs.startsWith("local:")) vs = vs.replaceFirst("^local:", "");
×
245
        if (!isUnifiableWith(v)) throw new UnificationException(vs);
×
246
        choice.setModelObject(vs);
×
247
    }
×
248

249
    /**
250
     * {@inheritDoc}
251
     */
252
    @Override
253
    public void fillFinished() {
254
    }
×
255

256
    /**
257
     * {@inheritDoc}
258
     */
259
    @Override
260
    public void finalizeValues() {
261
        Value defaultValue = context.getTemplate().getDefault(iri);
×
262
        if (isUnifiableWith(defaultValue)) {
×
263
            try {
264
                unifyWith(defaultValue);
×
265
            } catch (UnificationException ex) {
×
266
                logger.error("Could not unify with default value: {}", defaultValue, ex);
×
267
            }
×
268
        }
269
    }
×
270

271
    /**
272
     * <p>toString.</p>
273
     *
274
     * @return a {@link java.lang.String} object
275
     */
276
    public String toString() {
277
        return "[Restricted choice item: " + iri + "]";
×
278
    }
279

280

281
    /**
282
     * Validator for the restricted choice item.
283
     */
284
    protected class Validator extends InvalidityHighlighting implements IValidator<String> {
285

286
        private static final long serialVersionUID = 1L;
287

288
        /**
289
         * Default constructor.
290
         */
291
        public Validator() {
×
292
        }
×
293

294
        @Override
295
        public void validate(IValidatable<String> s) {
296
            if (!restrictedChoice.getPossibleValues().contains(s.getValue())) {
×
297
                s.error(new ValidationError("Invalid choice"));
×
298
            }
299
        }
×
300

301
    }
302

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