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

opensrp / opensrp-client-native-form / #60

15 Sep 2023 07:38AM UTC coverage: 66.084% (-0.1%) from 66.188%
#60

Pull #666

github-actions

web-flow
Merge dc7df0845 into f8c80cf2b
Pull Request #666: [Local merge] Optbp compression merge for

8437 of 12767 relevant lines covered (66.08%)

0.66 hits per line

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

90.98
android-json-form-wizard/src/main/java/com/vijay/jsonwizard/widgets/EditTextFactory.java
1
package com.vijay.jsonwizard.widgets;
2

3
import android.content.Context;
4
import android.text.Editable;
5
import android.text.InputFilter;
6
import android.text.InputType;
7
import android.text.TextUtils;
8
import android.text.TextWatcher;
9
import android.text.method.PasswordTransformationMethod;
10
import android.util.Patterns;
11
import android.view.LayoutInflater;
12
import android.view.View;
13
import android.widget.ImageView;
14
import android.widget.RelativeLayout;
15

16
import com.rengwuxian.materialedittext.MaterialEditText;
17
import com.rengwuxian.materialedittext.validation.METValidator;
18
import com.rengwuxian.materialedittext.validation.RegexpValidator;
19
import com.rey.material.util.ViewUtil;
20
import com.vijay.jsonwizard.R;
21
import com.vijay.jsonwizard.constants.JsonFormConstants;
22
import com.vijay.jsonwizard.customviews.GenericTextWatcher;
23
import com.vijay.jsonwizard.fragments.JsonFormFragment;
24
import com.vijay.jsonwizard.interfaces.CommonListener;
25
import com.vijay.jsonwizard.interfaces.FormWidgetFactory;
26
import com.vijay.jsonwizard.interfaces.JsonApi;
27
import com.vijay.jsonwizard.utils.FormUtils;
28
import com.vijay.jsonwizard.utils.ValidationStatus;
29
import com.vijay.jsonwizard.validators.edittext.CumulativeTotalValidator;
30
import com.vijay.jsonwizard.validators.edittext.MaxLengthValidator;
31
import com.vijay.jsonwizard.validators.edittext.MaxNumericValidator;
32
import com.vijay.jsonwizard.validators.edittext.MinLengthValidator;
33
import com.vijay.jsonwizard.validators.edittext.MinNumericValidator;
34
import com.vijay.jsonwizard.validators.edittext.ReferenceFieldValidator;
35
import com.vijay.jsonwizard.validators.edittext.ReferenceValidator;
36
import com.vijay.jsonwizard.validators.edittext.RelativeNumericValidator;
37
import com.vijay.jsonwizard.validators.edittext.RequiredValidator;
38
import com.vijay.jsonwizard.views.JsonFormFragmentView;
39

40
import org.apache.commons.lang3.StringUtils;
41
import org.json.JSONArray;
42
import org.json.JSONException;
43
import org.json.JSONObject;
44

45
import java.util.ArrayList;
46
import java.util.HashSet;
47
import java.util.List;
48
import java.util.Set;
49

50
import timber.log.Timber;
51

52
import static com.vijay.jsonwizard.constants.JsonFormConstants.DEFAULT_CUMULATIVE_VALIDATION_ERR;
53
import static com.vijay.jsonwizard.constants.JsonFormConstants.DEFAULT_RELATIVE_MAX_VALIDATION_ERR;
54
import static com.vijay.jsonwizard.constants.JsonFormConstants.DEFAULT_RELATIVE_MIN_VALIDATION_ERR;
55
import static com.vijay.jsonwizard.constants.JsonFormConstants.KEY;
56
import static com.vijay.jsonwizard.constants.JsonFormConstants.RELATED_FIELDS;
57
import static com.vijay.jsonwizard.constants.JsonFormConstants.RELATIVE_VALIDATION_EXCEPTION;
58
import static com.vijay.jsonwizard.constants.JsonFormConstants.STEP1;
59
import static com.vijay.jsonwizard.constants.JsonFormConstants.V_CUMULATIVE_TOTAL;
60
import static com.vijay.jsonwizard.constants.JsonFormConstants.V_RELATIVE_MAX;
61
import static com.vijay.jsonwizard.constants.JsonFormConstants.V_RELATIVE_MIN;
62
import static com.vijay.jsonwizard.utils.FormUtils.fields;
63
import static com.vijay.jsonwizard.utils.FormUtils.getFieldJSONObject;
64

65
public class EditTextFactory implements FormWidgetFactory {
1✔
66

67
    public static final int MIN_LENGTH = 0;
68
    public static final int MAX_LENGTH = 100;
69
    private FormUtils formUtils = new FormUtils();
1✔
70

71
    public static ValidationStatus validate(JsonFormFragmentView formFragmentView, MaterialEditText editText) {
72
        if (editText.isEnabled()) {
1✔
73
            boolean validate = editText.validate();
1✔
74
            if (!validate || (StringUtils.isBlank(editText.getText()) && getRequiredValidator(editText) != null)) {
1✔
75
                String errorString = null;
1✔
76
                if (editText != null && editText.getError() != null) {
1✔
77
                    errorString = editText.getError().toString();
1✔
78
                } else if (StringUtils.isBlank(editText.getText())) {
×
79
                    // Patching MaterialEditText to handle case
80
                    // when empty spaces are entered
81
                    METValidator validator = getRequiredValidator(editText);
×
82
                    errorString = validator.getErrorMessage();
×
83
                    editText.setError(errorString);
×
84
                }
85
                return new ValidationStatus(false, errorString, formFragmentView, editText);
1✔
86
            }
87
        }
88
        return new ValidationStatus(true, null, formFragmentView, editText);
1✔
89
    }
90

91
    private static METValidator getRequiredValidator(MaterialEditText editText) {
92
        if (editText.getValidators() != null) {
1✔
93
            for (METValidator validator : editText.getValidators()) {
×
94
                if (validator instanceof RequiredValidator) {
×
95
                    return validator;
×
96
                }
97
            }
×
98
        }
99
        return null;
1✔
100
    }
101

102
    @Override
103
    public List<View> getViewsFromJson(String stepName, Context context, JsonFormFragment formFragment,
104
                                       JSONObject jsonObject, CommonListener listener, boolean popup) throws Exception {
105
        return attachJson(stepName, context, formFragment, jsonObject, listener, popup);
1✔
106
    }
107

108
    @Override
109
    public List<View> getViewsFromJson(String stepName, Context context, JsonFormFragment formFragment,
110
                                       JSONObject jsonObject, CommonListener listener) throws Exception {
111
        return attachJson(stepName, context, formFragment, jsonObject, listener, false);
1✔
112
    }
113

114
    protected List<View> attachJson(String stepName, Context context, JsonFormFragment formFragment, JSONObject jsonObject,
115
                                    CommonListener listener, boolean popup) throws Exception {
116
        List<View> views = new ArrayList<>(1);
1✔
117

118
        RelativeLayout rootLayout = getRelativeLayout(context);
1✔
119
        RelativeLayout editTextLayout = rootLayout.findViewById(R.id.edit_text_layout);
1✔
120
        MaterialEditText editText = editTextLayout.findViewById(R.id.edit_text);
1✔
121
        ImageView editButton = editTextLayout.findViewById(R.id.material_edit_text_edit_button);
1✔
122
        FormUtils.setEditButtonAttributes(jsonObject, editText, editButton, listener);
1✔
123
        attachLayout(stepName, context, formFragment, jsonObject, editText, editButton);
1✔
124

125
        JSONArray canvasIds = new JSONArray();
1✔
126
        rootLayout.setId(ViewUtil.generateViewId());
1✔
127
        canvasIds.put(rootLayout.getId());
1✔
128
        editText.setTag(R.id.canvas_ids, canvasIds.toString());
1✔
129
        editText.setTag(R.id.extraPopup, popup);
1✔
130

131
        attachInfoIcon(stepName, jsonObject, rootLayout, canvasIds, listener);
1✔
132

133
        ((JsonApi) context).addFormDataView(editText);
1✔
134
        views.add(rootLayout);
1✔
135
        return views;
1✔
136
    }
137

138
    public RelativeLayout getRelativeLayout(Context context) {
139
        return (RelativeLayout) LayoutInflater.from(context).inflate(getLayout(), null);
1✔
140
    }
141

142
    protected int getLayout() {
143
        return R.layout.native_form_item_edit_text;
1✔
144
    }
145

146
    protected void attachLayout(String stepName, Context context, JsonFormFragment formFragment,
147
                                final JSONObject jsonObject, final MaterialEditText editText, ImageView editButton)
148
            throws Exception {
149

150
        String openMrsEntityParent = jsonObject.getString(JsonFormConstants.OPENMRS_ENTITY_PARENT);
1✔
151
        String openMrsEntity = jsonObject.getString(JsonFormConstants.OPENMRS_ENTITY);
1✔
152
        String openMrsEntityId = jsonObject.getString(JsonFormConstants.OPENMRS_ENTITY_ID);
1✔
153

154
        editText.setId(ViewUtil.generateViewId());
1✔
155
        editText.setTag(R.id.key, jsonObject.getString(JsonFormConstants.KEY));
1✔
156
        editText.setTag(R.id.openmrs_entity_parent, openMrsEntityParent);
1✔
157
        editText.setTag(R.id.openmrs_entity, openMrsEntity);
1✔
158
        editText.setTag(R.id.openmrs_entity_id, openMrsEntityId);
1✔
159
        editText.setTag(R.id.type, jsonObject.getString(JsonFormConstants.TYPE));
1✔
160
        editText.setTag(R.id.address, stepName + ":" + jsonObject.getString(JsonFormConstants.KEY));
1✔
161

162
        if (!TextUtils.isEmpty(jsonObject.optString(JsonFormConstants.VALUE))) {
1✔
163
            formFragment.getJsonApi().getAppExecutors().mainThread().execute(new Runnable() {
1✔
164
                @Override
165
                public void run() {
166
                    try {
167
                        editText.setText(jsonObject.optString(JsonFormConstants.VALUE));
1✔
168
                        editText.setSelection(editText.getText().length());
1✔
169
                    } catch (Exception e) {
×
170
                        Timber.e(e, "Catching an error throw on spannable, when loading report form");
×
171
                    }
1✔
172
                }
1✔
173
            });
174
        }
175
        if (jsonObject.has(JsonFormConstants.HINT)) {
1✔
176
            editText.setHint(jsonObject.getString(JsonFormConstants.HINT));
1✔
177
            editText.setFloatingLabelText(jsonObject.getString(JsonFormConstants.HINT));
1✔
178
        }
179
        FormUtils.setEditMode(jsonObject, editText, editButton);
1✔
180
        FormUtils.toggleEditTextVisibility(jsonObject, editText);
1✔
181

182
        addRequiredValidator(jsonObject, editText);
1✔
183
        addEqualsValidator(formFragment,jsonObject,editText);
1✔
184
        addLengthValidator(jsonObject, editText);
1✔
185
        addRegexValidator(jsonObject, editText);
1✔
186
        addEmailValidator(jsonObject, editText);
1✔
187
        addUrlValidator(jsonObject, editText);
1✔
188
        addNumericValidator(jsonObject, editText);
1✔
189
        addNumericIntegerValidator(jsonObject, editText);
1✔
190
        addRelativeNumericIntegerValidator(jsonObject, formFragment, editText, true);
1✔
191
        addRelativeNumericIntegerValidator(jsonObject, formFragment, editText, false);
1✔
192
        addCumulativeTotalValidator(jsonObject, formFragment, editText, stepName, (JsonApi) context);
1✔
193
        // edit type check
194
        String editType = jsonObject.optString(JsonFormConstants.EDIT_TYPE);
1✔
195
        editText.setSingleLine(false);
1✔
196
        if (!TextUtils.isEmpty(editType)) {
1✔
197
            if (JsonFormConstants.NUMBER.equals(editType)) {
1✔
198
                editText.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
1✔
199
            } else if (JsonFormConstants.NAME.equals(editType)) {
1✔
200
                editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_WORDS);
1✔
201
            }
202
            else if (JsonFormConstants.PASSWORD.equals(editType))
×
203
            {
204
                editText.setTransformationMethod(PasswordTransformationMethod.getInstance());
×
205
            }
206

207
        }
208
        editText.addTextChangedListener(new GenericTextWatcher(stepName, formFragment, editText));
1✔
209
        attachRefreshLogic(context, jsonObject, editText);
1✔
210
    }
1✔
211

212
    private void attachInfoIcon(String stepName, JSONObject jsonObject, RelativeLayout rootLayout, JSONArray canvasIds,
213
                                CommonListener listener) throws JSONException {
214
        if (jsonObject.has(JsonFormConstants.LABEL_INFO_TEXT) || jsonObject.has(JsonFormConstants.LABEL_INFO_HAS_IMAGE)) {
1✔
215
            ImageView infoIcon = rootLayout.findViewById(R.id.info_icon);
1✔
216
            formUtils.showInfoIcon(stepName, jsonObject, listener, FormUtils.getInfoDialogAttributes(jsonObject), infoIcon, canvasIds);
1✔
217
        }
218

219
    }
1✔
220

221
    private void addEqualsValidator(JsonFormFragment formFragment,JSONObject jsonObject, MaterialEditText editText) throws JSONException {
222
        JSONObject requiredObject = jsonObject.optJSONObject(JsonFormConstants.V_EQUALS);
1✔
223
        if (requiredObject != null) {
1✔
224
            String referencedValue = requiredObject.optString(JsonFormConstants.VALUE,"");
×
225
            MaterialEditText referencedEditText = (MaterialEditText) formFragment.getJsonApi().getFormDataView(referencedValue);
×
226
            editText.addValidator(new ReferenceFieldValidator(requiredObject.getString(JsonFormConstants.ERR),referencedEditText));
×
227
            FormUtils.setRequiredOnHint(editText);
×
228
        }
229
    }
1✔
230
    private void addRequiredValidator(JSONObject jsonObject, MaterialEditText editText) throws JSONException {
231
        JSONObject requiredObject = jsonObject.optJSONObject(JsonFormConstants.V_REQUIRED);
1✔
232
        if (requiredObject != null) {
1✔
233
            boolean requiredValue = requiredObject.getBoolean(JsonFormConstants.VALUE);
1✔
234
            if (Boolean.TRUE.equals(requiredValue)) {
1✔
235
                editText.addValidator(new RequiredValidator(requiredObject.getString(JsonFormConstants.ERR)));
1✔
236
                FormUtils.setRequiredOnHint(editText);
1✔
237
            }
238
        }
239
    }
1✔
240

241
    private void addLengthValidator(JSONObject jsonObject, MaterialEditText editText) throws JSONException {
242
        int minLength = MIN_LENGTH;
1✔
243
        int maxLength = MAX_LENGTH;
1✔
244
        boolean isRequired = fieldIsRequired(jsonObject);
1✔
245

246
        JSONObject minLengthObject = jsonObject.optJSONObject(JsonFormConstants.V_MIN_LENGTH);
1✔
247
        if (minLengthObject != null) {
1✔
248
            String minLengthValue = minLengthObject.optString(JsonFormConstants.VALUE);
1✔
249
            if (!TextUtils.isEmpty(minLengthValue)) {
1✔
250
                minLength = Integer.parseInt(minLengthValue);
1✔
251
                editText.addValidator(
1✔
252
                        new MinLengthValidator(
253
                                minLengthObject.getString(JsonFormConstants.ERR),
1✔
254
                                Integer.parseInt(minLengthValue),
1✔
255
                                isRequired
256
                        )
257
                );
258
            }
259
        }
260

261
        JSONObject maxLengthObject = jsonObject.optJSONObject(JsonFormConstants.V_MAX_LENGTH);
1✔
262
        if (maxLengthObject != null) {
1✔
263
            String maxLengthValue = maxLengthObject.optString(JsonFormConstants.VALUE);
1✔
264
            if (!TextUtils.isEmpty(maxLengthValue)) {
1✔
265
                maxLength = Integer.parseInt(maxLengthValue);
1✔
266
                editText.addValidator(
1✔
267
                        new MaxLengthValidator(
268
                                maxLengthObject.getString(JsonFormConstants.ERR),
1✔
269
                                Integer.parseInt(maxLengthValue),
1✔
270
                                isRequired
271
                        )
272
                );
273
                boolean iSFixedSize = maxLengthObject.optBoolean(JsonFormConstants.IS_FIXED_SIZE, false);
1✔
274
                if (iSFixedSize) {
1✔
275
                    editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)});
1✔
276
                }
277
            }
278
        }
279

280
        editText.setMaxCharacters(maxLength);
1✔
281
        editText.setMinCharacters(minLength);
1✔
282
    }
1✔
283

284
    private void addRegexValidator(JSONObject jsonObject, MaterialEditText editText) throws JSONException {
285
        JSONObject regexObject = jsonObject.optJSONObject(JsonFormConstants.V_REGEX);
1✔
286
        if (regexObject != null) {
1✔
287
            String regexValue = regexObject.optString(JsonFormConstants.VALUE);
1✔
288
            if (!TextUtils.isEmpty(regexValue)) {
1✔
289
                editText.addValidator(new RegexpValidator(regexObject.getString(JsonFormConstants.ERR), regexValue));
1✔
290
            }
291
        }
292
    }
1✔
293

294
    private void addEmailValidator(JSONObject jsonObject, MaterialEditText editText) throws JSONException {
295
        JSONObject emailObject = jsonObject.optJSONObject(JsonFormConstants.V_EMAIL);
1✔
296
        if (emailObject != null) {
1✔
297
            String emailValue = emailObject.optString(JsonFormConstants.VALUE);
1✔
298
            if (!TextUtils.isEmpty(emailValue) && Boolean.TRUE.toString().equalsIgnoreCase(emailValue)) {
1✔
299
                editText.addValidator(
1✔
300
                        new RegexpValidator(
301
                                emailObject.getString(JsonFormConstants.ERR),
1✔
302
                                android.util.Patterns.EMAIL_ADDRESS.toString()
1✔
303
                        )
304
                );
305
            }
306
        }
307
    }
1✔
308

309
    private void addUrlValidator(JSONObject jsonObject, MaterialEditText editText) throws JSONException {
310
        JSONObject urlObject = jsonObject.optJSONObject(JsonFormConstants.V_URL);
1✔
311
        if (urlObject != null) {
1✔
312
            String urlValue = urlObject.optString(JsonFormConstants.VALUE);
1✔
313
            if (!TextUtils.isEmpty(urlValue) && Boolean.TRUE.toString().equalsIgnoreCase(urlValue)) {
1✔
314
                editText.addValidator(
1✔
315
                        new RegexpValidator(
316
                                urlObject.getString(JsonFormConstants.ERR),
1✔
317
                                Patterns.WEB_URL.toString()
1✔
318
                        )
319
                );
320
            }
321
        }
322
    }
1✔
323

324
    private void addNumericValidator(JSONObject jsonObject, MaterialEditText editText) throws JSONException {
325
        JSONObject numericObject = jsonObject.optJSONObject(JsonFormConstants.V_NUMERIC);
1✔
326
        if (numericObject != null) {
1✔
327
            String numericValue = numericObject.optString(JsonFormConstants.VALUE);
1✔
328
            if (!TextUtils.isEmpty(numericValue) && Boolean.TRUE.toString().equalsIgnoreCase(numericValue)) {
1✔
329
                editText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
1✔
330
                editText.addValidator(
1✔
331
                        new RegexpValidator(numericObject.getString(JsonFormConstants.ERR), "[0-9]*\\.?[0-9]*")
1✔
332
                );
333

334
                if (jsonObject.has(JsonFormConstants.V_MIN)) {
1✔
335
                    JSONObject minValidation = jsonObject.getJSONObject(JsonFormConstants.V_MIN);
1✔
336
                    editText.addValidator(
1✔
337
                            new MinNumericValidator(
338
                                    minValidation.getString(JsonFormConstants.ERR),
1✔
339
                                    Double.parseDouble(minValidation.getString(JsonFormConstants.VALUE))
1✔
340
                            )
341
                    );
342
                }
343

344
                if (jsonObject.has(JsonFormConstants.V_MAX)) {
1✔
345
                    JSONObject minValidation = jsonObject.getJSONObject(JsonFormConstants.V_MAX);
1✔
346
                    editText.addValidator(
1✔
347
                            new MaxNumericValidator(
348
                                    minValidation.getString(JsonFormConstants.ERR),
1✔
349
                                    Double.parseDouble(minValidation.getString(JsonFormConstants.VALUE))
1✔
350
                            )
351
                    );
352
                }
353
            }
354
        }
355
    }
1✔
356

357
    private void addNumericIntegerValidator(JSONObject jsonObject, MaterialEditText editText) throws JSONException {
358
        JSONObject numericIntegerObject = jsonObject.optJSONObject(JsonFormConstants.V_NUMERIC_INTEGER);
1✔
359
        if (numericIntegerObject != null) {
1✔
360
            String numericValue = numericIntegerObject.optString(JsonFormConstants.VALUE);
1✔
361
            if (!TextUtils.isEmpty(numericValue) && Boolean.TRUE.toString().equalsIgnoreCase(numericValue)) {
1✔
362
                editText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED);
1✔
363
                editText.addValidator(new RegexpValidator(numericIntegerObject.getString(JsonFormConstants.ERR), "\\d*"));
1✔
364

365
                if (jsonObject.has(JsonFormConstants.V_MIN)) {
1✔
366
                    JSONObject minValidation = jsonObject.getJSONObject(JsonFormConstants.V_MIN);
1✔
367
                    editText.addValidator(
1✔
368
                            new MinNumericValidator(
369
                                    minValidation.getString(JsonFormConstants.ERR),
1✔
370
                                    Double.parseDouble(minValidation.getString(JsonFormConstants.VALUE))
1✔
371
                            )
372
                    );
373
                }
374

375
                if (jsonObject.has(JsonFormConstants.V_MAX)) {
1✔
376
                    JSONObject minValidation = jsonObject.getJSONObject(JsonFormConstants.V_MAX);
1✔
377
                    editText.addValidator(
1✔
378
                            new MaxNumericValidator(
379
                                    minValidation.getString(JsonFormConstants.ERR),
1✔
380
                                    Double.parseDouble(minValidation.getString(JsonFormConstants.VALUE))
1✔
381
                            )
382
                    );
383
                }
384
            }
385
        }
386
    }
1✔
387

388
    private void addRelativeNumericIntegerValidator(JSONObject editTextJSONObject, JsonFormFragment formFragment,
389
                                                    MaterialEditText editText, boolean isMaxValidator) throws JSONException {
390
        JSONObject relativeMaxValidationJSONObject = editTextJSONObject.optJSONObject(isMaxValidator ? V_RELATIVE_MAX : V_RELATIVE_MIN);
1✔
391
        if (relativeMaxValidationJSONObject != null) {
1✔
392
            // validate that the relative max field exists
393
            String relativeMaxValidationKey = relativeMaxValidationJSONObject.optString(JsonFormConstants.VALUE, null);
1✔
394
            JSONObject formJSONObject = new JSONObject(formFragment.getCurrentJsonState());
1✔
395
            JSONArray formFields = fields(formJSONObject, STEP1);
1✔
396
            JSONObject relativeMaxFieldJSONObject = getFieldJSONObject(formFields, relativeMaxValidationKey);
1✔
397
            if (relativeMaxFieldJSONObject != null) {
1✔
398
                // RELATIVE_MAX_VALIDATION_EXCEPTION, should never be set to Integer.MIN_VALUE in the native form json
399
                int relativeMaxValidationException = relativeMaxValidationJSONObject.optInt(RELATIVE_VALIDATION_EXCEPTION, 0);
1✔
400
                if (relativeMaxValidationException != Integer.MIN_VALUE) {
1✔
401
                    // add validator
402
                    String relativeMaxValidationErrorMsg = relativeMaxValidationJSONObject.optString(JsonFormConstants.ERR, null);
1✔
403
                    String defaultErrMsg = String.format(isMaxValidator ? DEFAULT_RELATIVE_MAX_VALIDATION_ERR : DEFAULT_RELATIVE_MIN_VALIDATION_ERR, relativeMaxValidationKey);
1✔
404
                    relativeMaxValidationException = relativeMaxValidationJSONObject.optInt(RELATIVE_VALIDATION_EXCEPTION, Integer.MIN_VALUE);
1✔
405
                    editText.addValidator(
1✔
406
                            new RelativeNumericValidator(
407
                                    relativeMaxValidationErrorMsg == null ? defaultErrMsg : relativeMaxValidationErrorMsg,
1✔
408
                                    formFragment,
409
                                    relativeMaxValidationKey,
410
                                    relativeMaxValidationException,
411
                                    STEP1,
412
                                    isMaxValidator
413
                            )
414
                    );
415
                }
416
            }
417
        }
418
    }
1✔
419

420
    private void addCumulativeTotalValidator(JSONObject editTextJSONObject, JsonFormFragment formFragment,
421
                                             final MaterialEditText editText, String stepName, JsonApi jsonApi) throws JSONException {
422
        JSONObject validationJSONObject = editTextJSONObject.optJSONObject(V_CUMULATIVE_TOTAL);
1✔
423
        if (validationJSONObject != null) {
1✔
424
            String totalValueKey = validationJSONObject.optString(JsonFormConstants.VALUE, null);
1✔
425
            JSONArray formFields = fields(new JSONObject(formFragment.getCurrentJsonState()), stepName);
1✔
426
            JSONObject totalFieldJSONObject = getFieldJSONObject(formFields, totalValueKey);
1✔
427
            if (totalFieldJSONObject != null) {
1✔
428
                String validationErrorMsg = validationJSONObject.optString(JsonFormConstants.ERR, null);
1✔
429
                JSONArray relatedFieldsJson = validationJSONObject.optJSONArray(RELATED_FIELDS);
1✔
430

431
                if (relatedFieldsJson != null) {
1✔
432
                    String errorMessage = String.format(
1✔
433
                            DEFAULT_CUMULATIVE_VALIDATION_ERR,
434
                            editTextJSONObject.get(KEY),
1✔
435
                            relatedFieldsJson.join(", "),
1✔
436
                            totalValueKey
437
                    );
438

439
                    final CumulativeTotalValidator cumulativeTotalValidator = new CumulativeTotalValidator(
1✔
440
                            validationErrorMsg == null ? errorMessage : validationErrorMsg,
1✔
441
                            formFragment,
442
                            stepName,
443
                            totalValueKey,
444
                            relatedFieldsJson,
445
                            jsonApi
446
                    );
447
                    editText.addValidator(cumulativeTotalValidator);
1✔
448
                    for (int i = 0; i < relatedFieldsJson.length(); i++) {
1✔
449
                        MaterialEditText relatedEditText = getViewUsingAddress(stepName, relatedFieldsJson.getString(i), jsonApi);
1✔
450
                        if (relatedEditText != null) {
1✔
451
                            ReferenceValidator referenceValidator = new ReferenceValidator(
1✔
452
                                    cumulativeTotalValidator.getErrorMessage(),
1✔
453
                                    cumulativeTotalValidator,
454
                                    relatedEditText,
455
                                    editText
456
                            );
457
                            relatedEditText.addValidator(referenceValidator);
1✔
458
                            cumulativeTotalValidator.getReferenceValidators().add(referenceValidator);
1✔
459
                        }
460
                    }
461

462
                    MaterialEditText totalValueView = getViewUsingAddress(stepName, totalValueKey, jsonApi);
1✔
463

464
                    totalValueView.addTextChangedListener(new TextWatcher() {
1✔
465
                        @Override
466
                        public void beforeTextChanged(CharSequence s, int start, int count, int after) {//do nothing
467
                        }
×
468

469
                        @Override
470
                        public void onTextChanged(CharSequence s, int start, int before, int count) {//do nothing
471
                        }
×
472

473
                        @Override
474
                        public void afterTextChanged(Editable s) {
475
                            if (!cumulativeTotalValidator.isValid(editText.getText(), TextUtils.isEmpty(s))
×
476
                                    && !TextUtils.isEmpty(editText.getText())) {
×
477
                                editText.setError(cumulativeTotalValidator.getErrorMessage());
×
478
                            }
479
                        }
×
480
                    });
481
                }
482
            }
483
        }
484
    }
1✔
485

486
    private void attachRefreshLogic(Context context, JSONObject jsonObject, MaterialEditText editText) {
487
        String relevance = jsonObject.optString(JsonFormConstants.RELEVANCE);
1✔
488
        String constraints = jsonObject.optString(JsonFormConstants.CONSTRAINTS);
1✔
489
        String calculation = jsonObject.optString(JsonFormConstants.CALCULATION);
1✔
490

491
        if (!TextUtils.isEmpty(relevance) && context instanceof JsonApi) {
1✔
492
            editText.setTag(R.id.relevance, relevance);
1✔
493
            ((JsonApi) context).addSkipLogicView(editText);
1✔
494
        }
495

496
        if (!TextUtils.isEmpty(constraints) && context instanceof JsonApi) {
1✔
497
            editText.setTag(R.id.constraints, constraints);
1✔
498
            ((JsonApi) context).addConstrainedView(editText);
1✔
499
        }
500

501
        if (!TextUtils.isEmpty(calculation) && context instanceof JsonApi) {
1✔
502
            editText.setTag(R.id.calculation, calculation);
1✔
503
            ((JsonApi) context).addCalculationLogicView(editText);
1✔
504
        }
505
    }
1✔
506

507
    private MaterialEditText getViewUsingAddress(String stepName, String fieldKey, JsonApi jsonApi) {
508
        View view = jsonApi.getFormDataView(stepName + ":" + fieldKey);
1✔
509
        if (view instanceof MaterialEditText)
1✔
510
            return (MaterialEditText) view;
1✔
511
        else
512
            return null;
×
513
    }
514

515
    @Override
516
    public Set<String> getCustomTranslatableWidgetFields() {
517
        Set<String> customTranslatableWidgetFields = new HashSet<>();
1✔
518
        customTranslatableWidgetFields.add(JsonFormConstants.LABEL_INFO_TITLE);
1✔
519
        customTranslatableWidgetFields.add(JsonFormConstants.LABEL_INFO_TEXT);
1✔
520
        return customTranslatableWidgetFields;
1✔
521
    }
522

523
    private boolean fieldIsRequired(JSONObject jsonObject) throws JSONException {
524
        JSONObject requiredObject = jsonObject.optJSONObject(JsonFormConstants.V_REQUIRED);
1✔
525
        return requiredObject != null && requiredObject.getBoolean(JsonFormConstants.VALUE);
1✔
526
    }
527
}
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