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

3
import com.knowledgepixels.nanodash.LocalUri;
4
import com.knowledgepixels.nanodash.NanodashSession;
5
import com.knowledgepixels.nanodash.User;
6
import com.knowledgepixels.nanodash.Utils;
7
import com.knowledgepixels.nanodash.component.IriTextfieldItem.Validator;
8
import com.knowledgepixels.nanodash.page.ProfilePage;
9
import com.knowledgepixels.nanodash.template.Template;
10
import com.knowledgepixels.nanodash.template.TemplateContext;
11
import com.knowledgepixels.nanodash.template.UnificationException;
12
import org.apache.wicket.Component;
13
import org.apache.wicket.ajax.AjaxRequestTarget;
14
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
15
import org.apache.wicket.behavior.AttributeAppender;
16
import org.apache.wicket.markup.html.basic.Label;
17
import org.apache.wicket.markup.html.link.ExternalLink;
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.nanopub.vocabulary.NTEMPLATE;
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.*;
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 AbstractContextComponent {
36

37
    private Select2Choice<String> textfield;
38
    private ExternalLink tooltipLink;
39
    private Label tooltipDescription;
40
    private IRI iri;
41
    private IModel<String> model;
42
    private static final Logger logger = LoggerFactory.getLogger(AgentChoiceItem.class);
×
43

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

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

78
        ChoiceProvider<String> choiceProvider = new ChoiceProvider<String>() {
×
79

80
            @Override
81
            public String getDisplayValue(String choiceId) {
82
                if (choiceId == null || choiceId.isEmpty()) return "";
×
83
                String label = getChoiceLabel(choiceId);
×
84
                if (label == null || label.isBlank()) {
×
85
                    return choiceId;
×
86
                }
87
                return label + " (" + choiceId + ")";
×
88
            }
89

90
            @Override
91
            public String getIdValue(String object) {
92
                return object;
×
93
            }
94

95
            // Getting strange errors with Tomcat if this method is not overridden:
96
            @Override
97
            public void detach() {
98
            }
×
99

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

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

151
            @Override
152
            public Collection<String> toChoices(Collection<String> ids) {
153
                return ids;
×
154
            }
155

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

166
        if (!optional) textfield.setRequired(true);
×
167
        textfield.add(new AttributeAppender("class", " wide"));
×
168
        textfield.add(new Validator(iri, template, "", context));
×
169
        context.getComponents().add(textfield);
×
170

171
        tooltipDescription = new Label("description", new IModel<String>() {
×
172

173
            @Override
174
            public String getObject() {
175
                String obj = AgentChoiceItem.this.getModel().getObject();
×
176
                if (obj == null || obj.isEmpty()) return "choose a value";
×
177
                String label = getChoiceLabel(AgentChoiceItem.this.getModel().getObject());
×
178
                if (label == null || !label.contains(" - ")) return "";
×
179
                return label.substring(label.indexOf(" - ") + 3);
×
180
            }
181

182
        });
183
        tooltipDescription.setOutputMarkupId(true);
×
184
        add(tooltipDescription);
×
185

186
        tooltipLink = Utils.getUriLink("uri", model);
×
187
        tooltipLink.setOutputMarkupId(true);
×
188
        add(tooltipLink);
×
189

190
        textfield.add(new OnChangeAjaxBehavior() {
×
191

192
            @Override
193
            protected void onUpdate(AjaxRequestTarget target) {
194
                for (Component c : context.getComponents()) {
×
195
                    if (c == textfield) continue;
×
196
                    if (c.getDefaultModel() == textfield.getModel()) {
×
197
                        c.modelChanged();
×
198
                        target.add(c);
×
199
                    }
200
                }
×
201
                target.add(tooltipLink);
×
202
                target.add(tooltipDescription);
×
203
            }
×
204

205
        });
206
        add(textfield);
×
207
    }
×
208

209
    /**
210
     * Returns the IRI of the agent choice item.
211
     *
212
     * @return the IRI of the agent choice item
213
     */
214
    public IModel<String> getModel() {
215
        return model;
×
216
    }
217

218
    /**
219
     * {@inheritDoc}
220
     */
221
    @Override
222
    public void removeFromContext() {
223
        context.getComponents().remove(textfield);
×
224
    }
×
225

226
    /**
227
     * {@inheritDoc}
228
     */
229
    @Override
230
    public boolean isUnifiableWith(Value v) {
231
        if (v == null) return true;
×
232
        if (v instanceof IRI) {
×
233
            String vs = v.stringValue();
×
234
            if (Utils.isLocalURI(vs)) vs = vs.replaceFirst("^" + LocalUri.PREFIX, "");
×
235
            Validatable<String> validatable = new Validatable<>(vs);
×
236
            if (context.getTemplate().isLocalResource(iri) && !Utils.isUriPostfix(vs)) {
×
237
                vs = Utils.getUriPostfix(vs);
×
238
            }
239
            new Validator(iri, context.getTemplate(), "", context).validate(validatable);
×
240
            if (!validatable.isValid()) {
×
241
                return false;
×
242
            }
243
            if (textfield.getModelObject().isEmpty()) {
×
244
                return true;
×
245
            }
246
            return vs.equals(textfield.getModelObject());
×
247
        }
248
        return false;
×
249
    }
250

251
    /**
252
     * {@inheritDoc}
253
     */
254
    @Override
255
    public void unifyWith(Value v) throws UnificationException {
256
        if (v == null) return;
×
257
        if (!isUnifiableWith(v)) throw new UnificationException(v.stringValue());
×
258
        String vs = v.stringValue();
×
259
        if (Utils.isLocalURI(vs)) {
×
260
            vs = vs.replaceFirst("^" + LocalUri.PREFIX, "");
×
261
        }
262
        textfield.setModelObject(vs);
×
263
    }
×
264

265
    /**
266
     * {@inheritDoc}
267
     */
268
    @Override
269
    public void fillFinished() {
270
    }
×
271

272
    /**
273
     * {@inheritDoc}
274
     */
275
    @Override
276
    public void finalizeValues() {
277
        Value defaultValue = context.getTemplate().getDefault(iri);
×
278
        if (NTEMPLATE.CREATOR_PLACEHOLDER.equals(defaultValue)) {
×
279
            defaultValue = NanodashSession.get().getUserIri();
×
280
        }
281
        if (isUnifiableWith(defaultValue)) {
×
282
            try {
283
                unifyWith(defaultValue);
×
284
            } catch (UnificationException ex) {
×
285
                logger.error("Could not unify default value: {}", defaultValue, ex);
×
286
            }
×
287
        }
288
    }
×
289

290
    /**
291
     * <p>toString.</p>
292
     *
293
     * @return a {@link java.lang.String} object
294
     */
295
    public String toString() {
296
        return "[Agent choiced item: " + iri + "]";
×
297
    }
298

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