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

knowledgepixels / nanodash / 17854474450

19 Sep 2025 09:32AM UTC coverage: 13.689% (-0.01%) from 13.701%
17854474450

push

github

tkuhn
feat: Full support of queries with multi-value params

435 of 4020 branches covered (10.82%)

Branch coverage included in aggregate %.

1114 of 7296 relevant lines covered (15.27%)

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

3
import java.net.URISyntaxException;
4

5
import org.apache.wicket.markup.html.basic.Label;
6
import org.apache.wicket.markup.html.form.FormComponent;
7
import org.apache.wicket.markup.html.form.TextArea;
8
import org.apache.wicket.markup.html.form.TextField;
9
import org.apache.wicket.markup.html.panel.Panel;
10
import org.apache.wicket.model.Model;
11
import org.apache.wicket.validation.INullAcceptingValidator;
12
import org.apache.wicket.validation.IValidatable;
13
import org.apache.wicket.validation.ValidationError;
14
import org.eclipse.rdf4j.common.net.ParsedIRI;
15

16
/**
17
 * A field for entering query parameters, with validation for required fields and IRIs.
18
 */
19
public class QueryParamField extends Panel {
20

21
    private final FormComponent<String> formComponent;
22
    private final String paramId;
23

24
    /**
25
     * Constructs a QueryParamField with the given ID and parameter ID.
26
     *
27
     * @param id      the Wicket component ID
28
     * @param paramId the parameter ID, which may start with underscores and end with "_iri"
29
     */
30
    public QueryParamField(String id, String paramId) {
31
        super(id);
×
32
        this.paramId = paramId;
×
33
        add(new Label("paramname", getParamName()));
×
34
        if (isMultiPlaceholder()) {
×
35
            add(new Label("textfield").setVisible(false));
×
36
            formComponent = new TextArea<>("textarea", Model.of(""));
×
37
        } else {
38
            formComponent = new TextField<>("textfield", Model.of(""));
×
39
            add(new Label("textarea").setVisible(false));
×
40
        }
41
        formComponent.add(new Validator());
×
42
        add(formComponent);
×
43
        add(new Label("marker", isOptional() ? "" : "*"));
×
44
    }
×
45

46
    /**
47
     * Returns the text field for entering the parameter value.
48
     *
49
     * @return the text field component
50
     */
51
    public FormComponent<String> getFormComponent() {
52
        return formComponent;
×
53
    }
54

55
    /**
56
     * Returns the values (multi) or single value (non-multi) entered in the text field.
57
     *
58
     * @return the value of the text field
59
     */
60
    public String[] getValues() {
61
        return expandValues(formComponent.getModelObject(), paramId);
×
62
    }
63

64
    /**
65
     * Returns the parameter ID.
66
     *
67
     * @return the parameter ID
68
     */
69
    public String getParamId() {
70
        return paramId;
×
71
    }
72

73
    /**
74
     * Returns the parameter name derived from the parameter ID.
75
     *
76
     * @return the parameter name
77
     */
78
    public String getParamName() {
79
        return getParamName(paramId);
×
80
    }
81

82
    /**
83
     * Sets the value of the field (non-multi) or adds the value to the list of values (multi).
84
     *
85
     * @param value the value to be set/added
86
     */
87
    public void putValue(String value) {
88
        if (value == null) return;
×
89
        if (isMultiPlaceholder()) {
×
90
            formComponent.getModel().setObject(formComponent.getModel().getObject() + value + "\n");
×
91
        } else {
92
            formComponent.getModel().setObject(value);
×
93
        }
94
    }
×
95

96
    /**
97
     * Checks if the parameter is optional (starts with "__").
98
     *
99
     * @return true if the parameter is optional, false otherwise
100
     */
101
    public boolean isOptional() {
102
        return paramId.startsWith("__");
×
103
    }
104

105
    /**
106
     * Checks if the parameter is an IRI parameter (ends with "_iri").
107
     *
108
     * @return true if the parameter is an IRI parameter, false otherwise
109
     */
110
    public boolean isIri() {
111
        return paramId.endsWith("_iri");
×
112
    }
113

114
    public boolean isSet() {
115
        return isSet(formComponent.getModelObject());
×
116
    }
117

118
    /**
119
     * Checks if the parameter is a multi parameter (ends with "_multi" or "_multi_iri").
120
     *
121
     * @return true if the parameter is a multi parameter, false otherwise
122
     */
123
    public boolean isMultiPlaceholder() {
124
        return isMultiPlaceholder(paramId);
×
125
    }
126

127
    private class Validator extends InvalidityHighlighting implements INullAcceptingValidator<String> {
×
128

129
        @Override
130
        public void validate(IValidatable<String> i) {
131
            if (isOptional() && !isSet()) {
×
132
                // all good
133
                return;
×
134
            }
135
            if (!isSet(i.getValue())) {
×
136
                i.error(new ValidationError("Missing value for " + paramId));
×
137
                return;
×
138
            }
139
            if (isIri()) {
×
140
                for (String value : expandValues(i.getValue(), paramId)) {
×
141
                    if (!value.matches("https?://.+")) {
×
142
                        i.error(new ValidationError("Invalid IRI protocol: " + value));
×
143
                        return;
×
144
                    }
145
                    try {
146
                        ParsedIRI piri = new ParsedIRI(value);
×
147
                        if (!piri.isAbsolute()) {
×
148
                            i.error(new ValidationError("IRI not well-formed: " + value));
×
149
                        }
150
                    } catch (URISyntaxException ex) {
×
151
                        i.error(new ValidationError("IRI not well-formed: " + value));
×
152
                    }
×
153
                }
154
            }
155
        }
×
156

157
    }
158

159
    public static boolean isSet(String s) {
160
        return s != null && !s.isBlank();
×
161
    }
162

163
    public static boolean isMultiPlaceholder(String p) {
164
        return p.endsWith("_multi") || p.endsWith("_multi_iri");
×
165
    }
166

167
    public static String[] expandValues(String s, String paramId) {
168
        if (!isSet(s)) {
×
169
            return new String[] {};
×
170
        } else if (isMultiPlaceholder(paramId)) {
×
171
            return s.replaceFirst("\r?\n$", "").split("\r?\n");
×
172
        } else {
173
            return new String[] { s };
×
174
        }
175
    }
176

177
    /**
178
     * Extracts the parameter name from the placeholder ID.
179
     *
180
     * @param placeholderId the placeholder ID, which may start with underscores and end with "_iri" and/or "_multi"
181
     * @return the parameter name, stripped of leading underscores and "_iri"/"_multi" suffixes
182
     */
183
    public static String getParamName(String placeholderId) {
184
        return placeholderId.replaceFirst("^_+", "").replaceFirst("_iri$", "").replaceFirst("_multi$", "");
×
185
    }
186

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