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

knowledgepixels / nanodash / 17302137193

28 Aug 2025 04:35PM UTC coverage: 11.965% (-0.4%) from 12.355%
17302137193

Pull #244

github

web-flow
Merge 4e969b0ee into 3323a35f1
Pull Request #244: Use vocabularies with latest version of `nanopub-java`

331 of 3840 branches covered (8.62%)

Branch coverage included in aggregate %.

943 of 6808 relevant lines covered (13.85%)

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

3
import com.knowledgepixels.nanodash.NanodashSession;
4
import com.knowledgepixels.nanodash.User;
5
import com.knowledgepixels.nanodash.Utils;
6
import com.knowledgepixels.nanodash.component.IriTextfieldItem.Validator;
7
import com.knowledgepixels.nanodash.page.ProfilePage;
8
import com.knowledgepixels.nanodash.template.Template;
9
import com.knowledgepixels.nanodash.template.TemplateContext;
10
import com.knowledgepixels.nanodash.template.UnificationException;
11
import org.apache.wicket.Component;
12
import org.apache.wicket.ajax.AjaxRequestTarget;
13
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
14
import org.apache.wicket.behavior.AttributeAppender;
15
import org.apache.wicket.markup.html.basic.Label;
16
import org.apache.wicket.markup.html.link.ExternalLink;
17
import org.apache.wicket.markup.html.panel.Panel;
18
import org.apache.wicket.model.IModel;
19
import org.apache.wicket.model.Model;
20
import org.apache.wicket.validation.Validatable;
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.nanopub.vocabulary.NTEMPLATE;
26
import org.wicketstuff.select2.ChoiceProvider;
27
import org.wicketstuff.select2.Response;
28
import org.wicketstuff.select2.Select2Choice;
29

30
import java.util.*;
31

32
/**
33
 * A component that allows users to select an agent (user) from a list or enter an ORCID or URL.
34
 */
35
public class AgentChoiceItem extends Panel implements ContextComponent {
36

37
    private static final long serialVersionUID = 1L;
38
    private TemplateContext context;
39
    private Select2Choice<String> textfield;
40
    private ExternalLink tooltipLink;
41
    private Label tooltipDescription;
42
    private IRI iri;
43
    private IModel<String> model;
44

45
    private String getChoiceLabel(String choiceId) {
46
        IRI iri = vf.createIRI(choiceId);
×
47
        String name = User.getName(iri);
×
48
        if (name != null) return name;
×
49
        return choiceId;
×
50
    }
51

52
    /**
53
     * Constructor for AgentChoiceItem.
54
     *
55
     * @param id       the component ID
56
     * @param parentId the parent component ID
57
     * @param iriP     the IRI of the agent choice item
58
     * @param optional whether the choice is optional
59
     * @param context  the template context
60
     */
61
    public AgentChoiceItem(String id, String parentId, final IRI iriP, boolean optional, final TemplateContext context) {
62
        super(id);
×
63
        this.context = context;
×
64
        this.iri = iriP;
×
65
        final Template template = context.getTemplate();
×
66
        model = context.getComponentModels().get(iri);
×
67
        if (model == null) {
×
68
            model = Model.of("");
×
69
            context.getComponentModels().put(iri, model);
×
70
        }
71
        String postfix = Utils.getUriPostfix(iri);
×
72
        if (context.hasParam(postfix)) {
×
73
            model.setObject(context.getParam(postfix));
×
74
        }
75
        final List<String> possibleValues = new ArrayList<>();
×
76
        for (Value v : template.getPossibleValues(iri)) {
×
77
            possibleValues.add(v.toString());
×
78
        }
×
79

80
        ChoiceProvider<String> choiceProvider = new ChoiceProvider<String>() {
×
81

82
            private static final long serialVersionUID = 1L;
83

84
            @Override
85
            public String getDisplayValue(String choiceId) {
86
                if (choiceId == null || choiceId.isEmpty()) return "";
×
87
                String label = getChoiceLabel(choiceId);
×
88
                if (label == null || label.isBlank()) {
×
89
                    return choiceId;
×
90
                }
91
                return label + " (" + choiceId + ")";
×
92
            }
93

94
            @Override
95
            public String getIdValue(String object) {
96
                return object;
×
97
            }
98

99
            // Getting strange errors with Tomcat if this method is not overridden:
100
            @Override
101
            public void detach() {
102
            }
×
103

104
            @Override
105
            public void query(String term, int page, Response<String> response) {
106
                if (term == null) {
×
107
                    if (possibleValues.isEmpty()) {
×
108
                        if (NanodashSession.get().getUserIri() != null) {
×
109
                            response.add(NanodashSession.get().getUserIri().stringValue());
×
110
                        }
111
                    } else {
112
                        response.addAll(possibleValues);
×
113
                    }
114
                    return;
×
115
                }
116
                if (term.startsWith("https://") || term.startsWith("http://")) {
×
117
                    response.add(term);
×
118
                } else if (term.matches(ProfilePage.ORCID_PATTERN)) {
×
119
                    response.add("https://orcid.org/" + term);
×
120
                }
121
                Map<String, Boolean> alreadyAddedMap = new HashMap<>();
×
122
                term = term.toLowerCase();
×
123
                for (String s : possibleValues) {
×
124
                    if (s.toLowerCase().contains(term) || getDisplayValue(s).toLowerCase().contains(term)) {
×
125
                        response.add(s);
×
126
                        alreadyAddedMap.put(s, true);
×
127
                    }
128
                }
×
129

130
                // TODO: We'll need some indexing to perform this more efficiently at some point:
131
                for (IRI iri : User.getUsers(true)) {
×
132
                    // Collect approved users
133
                    if (response.size() > 9) break;
×
134
                    if (response.getResults().contains(iri.stringValue())) continue;
×
135
                    String name = User.getName(iri);
×
136
                    if (iri.stringValue().contains(term)) {
×
137
                        response.add(iri.stringValue());
×
138
                    } else if (name != null && name.toLowerCase().contains(term)) {
×
139
                        response.add(iri.stringValue());
×
140
                    }
141
                }
×
142
                for (IRI iri : User.getUsers(false)) {
×
143
                    // Collect non-approved users
144
                    if (response.size() > 9) break;
×
145
                    if (response.getResults().contains(iri.stringValue())) continue;
×
146
                    String name = User.getName(iri);
×
147
                    if (iri.stringValue().contains(term)) {
×
148
                        response.add(iri.stringValue());
×
149
                    } else if (name != null && name.toLowerCase().contains(term)) {
×
150
                        response.add(iri.stringValue());
×
151
                    }
152
                }
×
153
            }
×
154

155
            @Override
156
            public Collection<String> toChoices(Collection<String> ids) {
157
                return ids;
×
158
            }
159

160
        };
161
        textfield = new Select2Choice<String>("textfield", model, choiceProvider);
×
162
        textfield.getSettings().getAjax(true).setDelay(500);
×
163
        textfield.getSettings().setCloseOnSelect(true);
×
164
        String placeholder = template.getLabel(iri);
×
165
        if (placeholder == null) placeholder = "select user or paste ORCID/URL";
×
166
        textfield.getSettings().setPlaceholder(placeholder);
×
167
        Utils.setSelect2ChoiceMinimalEscapeMarkup(textfield);
×
168
        textfield.getSettings().setAllowClear(true);
×
169

170
        if (!optional) textfield.setRequired(true);
×
171
        textfield.add(new AttributeAppender("class", " wide"));
×
172
        textfield.add(new Validator(iri, template, "", context));
×
173
        context.getComponents().add(textfield);
×
174

175
        tooltipDescription = new Label("description", new IModel<String>() {
×
176

177
            private static final long serialVersionUID = 1L;
178

179
            @Override
180
            public String getObject() {
181
                String obj = AgentChoiceItem.this.getModel().getObject();
×
182
                if (obj == null || obj.isEmpty()) return "choose a value";
×
183
                String label = getChoiceLabel(AgentChoiceItem.this.getModel().getObject());
×
184
                if (label == null || !label.contains(" - ")) return "";
×
185
                return label.substring(label.indexOf(" - ") + 3);
×
186
            }
187

188
        });
189
        tooltipDescription.setOutputMarkupId(true);
×
190
        add(tooltipDescription);
×
191

192
        tooltipLink = Utils.getUriLink("uri", model);
×
193
        tooltipLink.setOutputMarkupId(true);
×
194
        add(tooltipLink);
×
195

196
        textfield.add(new OnChangeAjaxBehavior() {
×
197

198
            private static final long serialVersionUID = 1L;
199

200
            @Override
201
            protected void onUpdate(AjaxRequestTarget target) {
202
                for (Component c : context.getComponents()) {
×
203
                    if (c == textfield) continue;
×
204
                    if (c.getDefaultModel() == textfield.getModel()) {
×
205
                        c.modelChanged();
×
206
                        target.add(c);
×
207
                    }
208
                }
×
209
                target.add(tooltipLink);
×
210
                target.add(tooltipDescription);
×
211
            }
×
212

213
        });
214
        add(textfield);
×
215
    }
×
216

217
    /**
218
     * Returns the IRI of the agent choice item.
219
     *
220
     * @return the IRI of the agent choice item
221
     */
222
    public IModel<String> getModel() {
223
        return model;
×
224
    }
225

226
    /**
227
     * {@inheritDoc}
228
     */
229
    @Override
230
    public void removeFromContext() {
231
        context.getComponents().remove(textfield);
×
232
    }
×
233

234
    /**
235
     * {@inheritDoc}
236
     */
237
    @Override
238
    public boolean isUnifiableWith(Value v) {
239
        if (v == null) return true;
×
240
        if (v instanceof IRI) {
×
241
            String vs = v.stringValue();
×
242
            if (vs.startsWith("local:")) vs = vs.replaceFirst("^local:", "");
×
243
            Validatable<String> validatable = new Validatable<>(vs);
×
244
            if (context.getTemplate().isLocalResource(iri) && !Utils.isUriPostfix(vs)) {
×
245
                vs = Utils.getUriPostfix(vs);
×
246
            }
247
            new Validator(iri, context.getTemplate(), "", context).validate(validatable);
×
248
            if (!validatable.isValid()) {
×
249
                return false;
×
250
            }
251
            if (textfield.getModelObject().isEmpty()) {
×
252
                return true;
×
253
            }
254
            return vs.equals(textfield.getModelObject());
×
255
        }
256
        return false;
×
257
    }
258

259
    /**
260
     * {@inheritDoc}
261
     */
262
    @Override
263
    public void unifyWith(Value v) throws UnificationException {
264
        if (v == null) return;
×
265
        if (!isUnifiableWith(v)) throw new UnificationException(v.stringValue());
×
266
        String vs = v.stringValue();
×
267
        if (vs.startsWith("local:")) {
×
268
            vs = vs.replaceFirst("^local:", "");
×
269
        }
270
        textfield.setModelObject(vs);
×
271
    }
×
272

273
    /**
274
     * {@inheritDoc}
275
     */
276
    @Override
277
    public void fillFinished() {
278
    }
×
279

280
    /**
281
     * {@inheritDoc}
282
     */
283
    @Override
284
    public void finalizeValues() {
285
        Value defaultValue = context.getTemplate().getDefault(iri);
×
286
        if (NTEMPLATE.CREATOR_PLACEHOLDER.equals(defaultValue)) {
×
287
            defaultValue = NanodashSession.get().getUserIri();
×
288
        }
289
        if (isUnifiableWith(defaultValue)) {
×
290
            try {
291
                unifyWith(defaultValue);
×
292
            } catch (UnificationException ex) {
×
293
                ex.printStackTrace();
×
294
            }
×
295
        }
296
    }
×
297

298
    private static ValueFactory vf = SimpleValueFactory.getInstance();
×
299

300
    /**
301
     * <p>toString.</p>
302
     *
303
     * @return a {@link java.lang.String} object
304
     */
305
    public String toString() {
306
        return "[Agent choiced item: " + iri + "]";
×
307
    }
308

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