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

hazendaz / httpunit / 755

14 Feb 2026 07:14PM UTC coverage: 80.526%. Remained the same
755

push

github

hazendaz
[ci] Fix badge

3213 of 4105 branches covered (78.27%)

Branch coverage included in aggregate %.

8245 of 10124 relevant lines covered (81.44%)

0.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.41
/src/main/java/com/meterware/httpunit/FormParameter.java
1
/*
2
 * SPDX-License-Identifier: MIT
3
 * See LICENSE file for details.
4
 *
5
 * Copyright 2000-2026 Russell Gold
6
 * Copyright 2021-2000 hazendaz
7
 */
8
package com.meterware.httpunit;
9

10
import com.meterware.httpunit.protocol.UploadFileSpec;
11
import com.meterware.httpunit.scripting.ScriptableDelegate;
12

13
import java.util.ArrayList;
14
import java.util.Arrays;
15

16
/**
17
 * Represents the aggregate of all form controls with a particular name. This permits us to abstract setting values so
18
 * that changing a control type does not break a test.
19
 **/
20
public class FormParameter {
1✔
21

22
    /** The Constant UNKNOWN_PARAMETER. */
23
    private static final FormParameter UNKNOWN_PARAMETER = new FormParameter();
1✔
24

25
    /** The controls. */
26
    private FormControl[] _controls;
27

28
    /** The control list. */
29
    private ArrayList _controlList = new ArrayList<>();
1✔
30

31
    /** The group. */
32
    private RadioGroupFormControl _group;
33

34
    /** The name. */
35
    private String _name;
36

37
    /**
38
     * Gets the unknown parameter.
39
     *
40
     * @return the uNKNOWN_PARAMETER
41
     */
42
    public static FormParameter getUNKNOWN_PARAMETER() {
43
        return UNKNOWN_PARAMETER;
1✔
44
    }
45

46
    /**
47
     * return whether I am the unknown parameter.
48
     *
49
     * @return true, if is unknown
50
     */
51
    public boolean isUnknown() {
52
        return this == UNKNOWN_PARAMETER;
1✔
53
    }
54

55
    /**
56
     * add the given form control.
57
     *
58
     * @param control
59
     *            the control
60
     */
61
    void addControl(FormControl control) {
62
        _controls = null;
1✔
63
        if (_name == null) {
1✔
64
            _name = control.getName();
1✔
65
        }
66
        if (!_name.equalsIgnoreCase(control.getName())) {
1!
67
            throw new RuntimeException("all controls should have the same name");
×
68
        }
69
        if (control.isExclusive()) {
1✔
70
            getRadioGroup(control.getForm()).addRadioButton((RadioButtonFormControl) control);
1✔
71
        } else {
72
            _controlList.add(control);
1✔
73
        }
74
    }
1✔
75

76
    /**
77
     * get the controls for this form Parameter.
78
     *
79
     * @return the controls
80
     */
81
    public FormControl[] getControls() {
82
        if (_controls == null) {
1✔
83
            _controls = (FormControl[]) _controlList.toArray(new FormControl[_controlList.size()]);
1✔
84
        }
85
        return _controls;
1✔
86
    }
87

88
    /**
89
     * get the control for this form Parameter (assuming it has only one as for a text control.
90
     *
91
     * @return the controls
92
     */
93
    public FormControl getControl() {
94
        FormControl[] controls = getControls();
×
95
        if (controls.length != 1) {
×
96
            throw new RuntimeException("getControl can only be called if the number of controls is 1 but it is "
×
97
                    + controls.length + " you might want to use getControls instead");
98
        }
99
        return controls[0];
×
100
    }
101

102
    /**
103
     * Gets the scriptable object.
104
     *
105
     * @return the scriptable object
106
     */
107
    Object getScriptableObject() {
108
        if (getControls().length == 1) {
1✔
109
            return getControls()[0].getDelegate();
1✔
110
        }
111
        ArrayList list = new ArrayList<>();
1✔
112
        for (FormControl control : _controls) {
1✔
113
            list.add(control.getScriptingHandler());
1✔
114
        }
115
        return list.toArray(new ScriptableDelegate[list.size()]);
1✔
116
    }
117

118
    /**
119
     * Gets the values.
120
     *
121
     * @return the values
122
     */
123
    String[] getValues() {
124
        ArrayList valueList = new ArrayList<>();
1✔
125
        FormControl[] controls = getControls();
1✔
126
        for (FormControl control : controls) {
1✔
127
            valueList.addAll(Arrays.asList(control.getValues()));
1✔
128
        }
129
        return (String[]) valueList.toArray(new String[valueList.size()]);
1✔
130
    }
131

132
    /**
133
     * set values to the given values.
134
     *
135
     * @param values
136
     *            the new values
137
     */
138
    void setValues(String[] values) {
139
        ArrayList list = new ArrayList(values.length);
1✔
140
        list.addAll(Arrays.asList(values));
1✔
141
        FormControl[] controls = getControls();
1✔
142
        for (FormControl control : controls) {
1✔
143
            control.claimRequiredValues(list);
1✔
144
        }
145
        for (FormControl control : controls) {
1✔
146
            control.claimUniqueValue(list);
1✔
147
        }
148
        for (FormControl control : controls) {
1✔
149
            control.claimValue(list);
1✔
150
        }
151
        if (!list.isEmpty()) {
1✔
152
            throw new UnusedParameterValueException(_name, (String) list.get(0));
1✔
153
        }
154
    }
1✔
155

156
    /**
157
     * Toggle checkbox.
158
     */
159
    public void toggleCheckbox() {
160
        FormControl[] controls = getControls();
1✔
161
        if (controls.length != 1) {
1!
162
            throw new IllegalCheckboxParameterException(_name, "toggleCheckbox");
×
163
        }
164
        controls[0].toggle();
1✔
165
    }
1✔
166

167
    /**
168
     * Toggle checkbox.
169
     *
170
     * @param value
171
     *            the value
172
     */
173
    public void toggleCheckbox(String value) {
174
        FormControl[] controls = getControls();
1✔
175
        for (FormControl control : controls) {
1!
176
            if (value.equals(control.getValueAttribute())) {
1!
177
                control.toggle();
1✔
178
                return;
1✔
179
            }
180
        }
181
        throw new IllegalCheckboxParameterException(_name + "/" + value, "toggleCheckbox");
×
182
    }
183

184
    /**
185
     * Sets the value.
186
     *
187
     * @param state
188
     *            the new value
189
     */
190
    public void setValue(boolean state) {
191
        FormControl[] controls = getControls();
1✔
192
        if (controls.length != 1) {
1✔
193
            throw new IllegalCheckboxParameterException(_name, "setCheckbox");
1✔
194
        }
195
        controls[0].setState(state);
1✔
196
    }
1✔
197

198
    /**
199
     * Sets the value.
200
     *
201
     * @param value
202
     *            the value
203
     * @param state
204
     *            the state
205
     */
206
    public void setValue(String value, boolean state) {
207
        FormControl[] controls = getControls();
1✔
208
        for (FormControl control : controls) {
1✔
209
            if (value.equals(control.getValueAttribute())) {
1✔
210
                control.setState(state);
1✔
211
                return;
1✔
212
            }
213
        }
214
        throw new IllegalCheckboxParameterException(_name + "/" + value, "setCheckbox");
1✔
215
    }
216

217
    /**
218
     * Sets the files.
219
     *
220
     * @param fileArray
221
     *            the new files
222
     */
223
    void setFiles(UploadFileSpec[] fileArray) {
224
        ArrayList list = new ArrayList(fileArray.length);
1✔
225
        list.addAll(Arrays.asList(fileArray));
1✔
226
        for (int i = 0; i < getControls().length; i++) {
1✔
227
            getControls()[i].claimUploadSpecification(list);
1✔
228
        }
229
        if (!list.isEmpty()) {
1✔
230
            throw new UnusedUploadFileException(_name, fileArray.length - list.size(), fileArray.length);
1✔
231
        }
232
    }
1✔
233

234
    /**
235
     * Gets the options.
236
     *
237
     * @return the options
238
     */
239
    String[] getOptions() {
240
        ArrayList optionList = new ArrayList<>();
1✔
241
        FormControl[] controls = getControls();
1✔
242
        for (FormControl control : controls) {
1✔
243
            optionList.addAll(Arrays.asList(control.getDisplayedOptions()));
1✔
244
        }
245
        return (String[]) optionList.toArray(new String[optionList.size()]);
1✔
246
    }
247

248
    /**
249
     * Gets the option values.
250
     *
251
     * @return the option values
252
     */
253
    String[] getOptionValues() {
254
        ArrayList valueList = new ArrayList<>();
1✔
255
        for (int i = 0; i < getControls().length; i++) {
1✔
256
            valueList.addAll(Arrays.asList(getControls()[i].getOptionValues()));
1✔
257
        }
258
        return (String[]) valueList.toArray(new String[valueList.size()]);
1✔
259
    }
260

261
    /**
262
     * Checks if is multi valued parameter.
263
     *
264
     * @return true, if is multi valued parameter
265
     */
266
    boolean isMultiValuedParameter() {
267
        FormControl[] controls = getControls();
×
268
        for (FormControl control : controls) {
×
269
            if (control.isMultiValued() || !control.isExclusive() && controls.length > 1) {
×
270
                return true;
×
271
            }
272
        }
273
        return false;
×
274
    }
275

276
    /**
277
     * Gets the num text parameters.
278
     *
279
     * @return the num text parameters
280
     */
281
    int getNumTextParameters() {
282
        int result = 0;
1✔
283
        FormControl[] controls = getControls();
1✔
284
        for (FormControl control : controls) {
1✔
285
            if (control.isTextControl()) {
1!
286
                result++;
1✔
287
            }
288
        }
289
        return result;
1✔
290
    }
291

292
    /**
293
     * Checks if is text parameter.
294
     *
295
     * @return true, if is text parameter
296
     */
297
    boolean isTextParameter() {
298
        FormControl[] controls = getControls();
×
299
        for (FormControl control : controls) {
×
300
            if (control.isTextControl()) {
×
301
                return true;
×
302
            }
303
        }
304
        return false;
×
305
    }
306

307
    /**
308
     * Checks if is file parameter.
309
     *
310
     * @return true, if is file parameter
311
     */
312
    boolean isFileParameter() {
313
        FormControl[] controls = getControls();
1✔
314
        for (FormControl control : controls) {
1✔
315
            if (control.isFileParameter()) {
1✔
316
                return true;
1✔
317
            }
318
        }
319
        return false;
1✔
320
    }
321

322
    /**
323
     * is this a disabled parameter.
324
     *
325
     * @return false if one of the controls is not disabled or this is the unknown parameter
326
     */
327
    boolean isDisabledParameter() {
328
        FormControl[] controls = getControls();
1✔
329
        for (FormControl control : controls) {
1✔
330
            if (!control.isDisabled()) {
1✔
331
                return false;
1✔
332
            }
333
        }
334
        return !this.isUnknown();
1✔
335
    }
336

337
    /**
338
     * is this a read only parameter.
339
     *
340
     * @return false if one of the controls is not read only or this is the unknown parameter
341
     */
342
    boolean isReadOnlyParameter() {
343
        FormControl[] controls = getControls();
1✔
344
        for (FormControl control : controls) {
1✔
345
            if (!control.isReadOnly()) {
1✔
346
                return false;
1✔
347
            }
348
        }
349
        return !this.isUnknown();
1✔
350
    }
351

352
    /**
353
     * is this a hidden parameter?.
354
     *
355
     * @return false if one of the controls is not hidden or this is the unknown parameter
356
     */
357
    public boolean isHiddenParameter() {
358
        FormControl[] controls = getControls();
1✔
359
        for (FormControl control : controls) {
1✔
360
            if (!control.isHidden()) {
1✔
361
                return false;
1✔
362
            }
363
        }
364
        return !this.isUnknown();
1✔
365
    }
366

367
    /**
368
     * Gets the radio group.
369
     *
370
     * @param form
371
     *            the form
372
     *
373
     * @return the radio group
374
     */
375
    private RadioGroupFormControl getRadioGroup(WebForm form) {
376
        if (_group == null) {
1✔
377
            _group = new RadioGroupFormControl(form);
1✔
378
            _controlList.add(_group);
1✔
379
        }
380
        return _group;
1✔
381
    }
382

383
    // ============================= exception class UnusedParameterValueException
384
    // ======================================
385

386
    /**
387
     * This exception is thrown on an attempt to set a parameter to a value not permitted to it by the form.
388
     **/
389
    public class UnusedParameterValueException extends IllegalRequestParameterException {
390

391
        /** The Constant serialVersionUID. */
392
        private static final long serialVersionUID = 1L;
393

394
        /**
395
         * construct an exception for an unused parameter with the given name and the value that is bad.
396
         *
397
         * @param parameterName
398
         *            the parameter name
399
         * @param badValue
400
         *            the bad value
401
         */
402
        UnusedParameterValueException(String parameterName, String badValue) {
1✔
403
            _parameterName = parameterName;
1✔
404
            _badValue = badValue;
1✔
405
        }
1✔
406

407
        /**
408
         * get the message for this exception
409
         *
410
         * @return the message
411
         */
412
        @Override
413
        public String getMessage() {
414
            StringBuilder sb = new StringBuilder(HttpUnitUtils.DEFAULT_TEXT_BUFFER_SIZE);
1✔
415
            sb.append("Attempted to assign to parameter '").append(_parameterName);
1✔
416
            sb.append("' the extraneous value '").append(_badValue).append("'.");
1✔
417
            return sb.toString();
1✔
418
        }
419

420
        /** The parameter name. */
421
        private String _parameterName;
422

423
        /** The bad value. */
424
        private String _badValue;
425
    }
426

427
    // ============================= exception class UnusedUploadFileException ======================================
428

429
    /**
430
     * This exception is thrown on an attempt to upload more files than permitted by the form.
431
     **/
432
    class UnusedUploadFileException extends IllegalRequestParameterException {
433

434
        /** The Constant serialVersionUID. */
435
        private static final long serialVersionUID = 1L;
436

437
        /**
438
         * construct a new UnusedUploadFileException exception base on the parameter Name the number of files expected
439
         * and supplied.
440
         *
441
         * @param parameterName
442
         *            the parameter name
443
         * @param numFilesExpected
444
         *            the num files expected
445
         * @param numFilesSupplied
446
         *            the num files supplied
447
         */
448
        UnusedUploadFileException(String parameterName, int numFilesExpected, int numFilesSupplied) {
1✔
449
            _parameterName = parameterName;
1✔
450
            _numExpected = numFilesExpected;
1✔
451
            _numSupplied = numFilesSupplied;
1✔
452
        }
1✔
453

454
        /**
455
         * get the message for this exception
456
         */
457
        @Override
458
        public String getMessage() {
459
            StringBuilder sb = new StringBuilder(HttpUnitUtils.DEFAULT_TEXT_BUFFER_SIZE);
×
460
            sb.append("Attempted to upload ").append(_numSupplied).append(" files using parameter '")
×
461
                    .append(_parameterName);
×
462
            if (_numExpected == 0) {
×
463
                sb.append("' which is not a file parameter.");
×
464
            } else {
465
                sb.append("' which only has room for ").append(_numExpected).append('.');
×
466
            }
467
            return sb.toString();
×
468
        }
469

470
        /** The parameter name. */
471
        private String _parameterName;
472

473
        /** The num expected. */
474
        private int _numExpected;
475

476
        /** The num supplied. */
477
        private int _numSupplied;
478
    }
479

480
    // ============================= exception class IllegalCheckboxParameterException
481
    // ======================================
482

483
    /**
484
     * This exception is thrown on an attempt to set a parameter to a value not permitted to it by the form.
485
     **/
486
    static class IllegalCheckboxParameterException extends IllegalRequestParameterException {
487

488
        /** The Constant serialVersionUID. */
489
        private static final long serialVersionUID = 1L;
490

491
        /**
492
         * Instantiates a new illegal checkbox parameter exception.
493
         *
494
         * @param parameterName
495
         *            the parameter name
496
         * @param methodName
497
         *            the method name
498
         */
499
        IllegalCheckboxParameterException(String parameterName, String methodName) {
1✔
500
            _parameterName = parameterName;
1✔
501
            _methodName = methodName;
1✔
502
        }
1✔
503

504
        @Override
505
        public String getMessage() {
506
            StringBuilder sb = new StringBuilder(HttpUnitUtils.DEFAULT_TEXT_BUFFER_SIZE);
×
507
            sb.append("Attempted to invoke method '").append(_methodName);
×
508
            sb.append("' for parameter '").append(_parameterName).append("', which is not a unique checkbox control.");
×
509
            return sb.toString();
×
510
        }
511

512
        /** The parameter name. */
513
        private String _parameterName;
514

515
        /** The method name. */
516
        private String _methodName;
517
    }
518

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