-
Notifications
You must be signed in to change notification settings - Fork 52
fix(QTDI-2489): Apply default value before required validation for absent keys #1254
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
32bc958
14061d6
a21aaab
0f0258e
6e5c56d
0c290e6
8b4da72
f32dff1
86ba178
147a8bb
55b3803
82eb7ab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -913,95 +913,126 @@ public void onParameter(final ParameterMeta meta, final JsonValue value) { | |
| return; | ||
| } | ||
|
|
||
| if (Boolean.parseBoolean(meta.getMetadata().get("tcomp::validation::required")) | ||
| && value == JsonValue.NULL) { | ||
| if (isRequiredAndMissingWithoutDefault(meta, value)) { | ||
| errors.add(MESSAGES.required(meta.getPath())); | ||
| } | ||
| final Map<String, String> metadata = meta.getMetadata(); | ||
| { | ||
| final String min = metadata.get("tcomp::validation::min"); | ||
| if (min != null) { | ||
| final double bound = Double.parseDouble(min); | ||
| if (value.getValueType() == JsonValue.ValueType.NUMBER | ||
| && ((JsonNumber) value).doubleValue() < bound) { | ||
| errors.add(MESSAGES.min(meta.getPath(), bound, ((JsonNumber) value).doubleValue())); | ||
| } | ||
| validateRuleMin(meta, value, metadata); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Following Sonar comment: reduce method complexity. Each block has been extracted as a method
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Acknowledged — this is a self-annotation explaining the Round 2/4 Sonar-driven refactor (cognitive complexity extraction). No further code change needed here. |
||
| validateRuleMax(meta, value, metadata); | ||
| validateRuleMinLength(meta, value, metadata); | ||
| validateRuleMaxLength(meta, value, metadata); | ||
| validateRuleMinItems(meta, value, metadata); | ||
| validateRuleMaxItems(meta, value, metadata); | ||
| validateRuleUniqueItems(meta, value, metadata); | ||
| validateRulePattern(meta, value, metadata); | ||
| } | ||
|
|
||
| private void validateRulePattern(final ParameterMeta meta, final JsonValue value, | ||
| final Map<String, String> metadata) { | ||
| final String pattern = metadata.get("tcomp::validation::pattern"); | ||
| if (pattern != null && value.getValueType() == JsonValue.ValueType.STRING) { | ||
| final String val = ((JsonString) value).getString(); | ||
| if (!new JavascriptRegex(pattern).test(val)) { | ||
| errors.add(MESSAGES.pattern(meta.getPath(), pattern)); | ||
| } | ||
| } | ||
| { | ||
| final String max = metadata.get("tcomp::validation::max"); | ||
| if (max != null) { | ||
| final double bound = Double.parseDouble(max); | ||
| if (value.getValueType() == JsonValue.ValueType.NUMBER | ||
| && ((JsonNumber) value).doubleValue() > bound) { | ||
| errors.add(MESSAGES.max(meta.getPath(), bound, ((JsonNumber) value).doubleValue())); | ||
| } | ||
| } | ||
|
|
||
| private void validateRuleUniqueItems(final ParameterMeta meta, final JsonValue value, | ||
| final Map<String, String> metadata) { | ||
| final String unique = metadata.get("tcomp::validation::uniqueItems"); | ||
| if (unique != null && value.getValueType() == JsonValue.ValueType.ARRAY) { | ||
| final JsonArray array = value.asJsonArray(); | ||
| if (new HashSet<>(array).size() != array.size()) { | ||
| errors.add(MESSAGES.uniqueItems(meta.getPath())); | ||
| } | ||
| } | ||
| { | ||
| final String min = metadata.get("tcomp::validation::minLength"); | ||
| if (min != null) { | ||
| final double bound = Double.parseDouble(min); | ||
| if (value.getValueType() == JsonValue.ValueType.STRING) { | ||
| final String val = ((JsonString) value).getString(); | ||
| if (val.length() < bound) { | ||
| errors.add(MESSAGES.minLength(meta.getPath(), bound, val.length())); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private void validateRuleMaxItems(final ParameterMeta meta, final JsonValue value, | ||
| final Map<String, String> metadata) { | ||
| final String max = metadata.get("tcomp::validation::maxItems"); | ||
| if (max != null) { | ||
| final double bound = Double.parseDouble(max); | ||
| if (value.getValueType() == JsonValue.ValueType.ARRAY && value.asJsonArray().size() > bound) { | ||
| errors.add(MESSAGES.maxItems(meta.getPath(), bound, value.asJsonArray().size())); | ||
| } | ||
| } | ||
| { | ||
| final String max = metadata.get("tcomp::validation::maxLength"); | ||
| if (max != null) { | ||
| final double bound = Double.parseDouble(max); | ||
| if (value.getValueType() == JsonValue.ValueType.STRING) { | ||
| final String val = ((JsonString) value).getString(); | ||
| if (val.length() > bound) { | ||
| errors.add(MESSAGES.maxLength(meta.getPath(), bound, val.length())); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private void validateRuleMinItems(final ParameterMeta meta, final JsonValue value, | ||
| final Map<String, String> metadata) { | ||
| final String min = metadata.get("tcomp::validation::minItems"); | ||
| if (min != null) { | ||
| final double bound = Double.parseDouble(min); | ||
| if (value.getValueType() == JsonValue.ValueType.ARRAY && value.asJsonArray().size() < bound) { | ||
| errors.add(MESSAGES.minItems(meta.getPath(), bound, value.asJsonArray().size())); | ||
| } | ||
| } | ||
| { | ||
| final String min = metadata.get("tcomp::validation::minItems"); | ||
| if (min != null) { | ||
| final double bound = Double.parseDouble(min); | ||
| if (value.getValueType() == JsonValue.ValueType.ARRAY && value.asJsonArray().size() < bound) { | ||
| errors.add(MESSAGES.minItems(meta.getPath(), bound, value.asJsonArray().size())); | ||
| } | ||
|
|
||
| private void validateRuleMaxLength(final ParameterMeta meta, final JsonValue value, | ||
| final Map<String, String> metadata) { | ||
| final String max = metadata.get("tcomp::validation::maxLength"); | ||
| if (max != null) { | ||
| final double bound = Double.parseDouble(max); | ||
| if (value.getValueType() == JsonValue.ValueType.STRING) { | ||
| final String val = ((JsonString) value).getString(); | ||
| if (val.length() > bound) { | ||
| errors.add(MESSAGES.maxLength(meta.getPath(), bound, val.length())); | ||
| } | ||
| } | ||
| } | ||
| { | ||
| final String max = metadata.get("tcomp::validation::maxItems"); | ||
| if (max != null) { | ||
| final double bound = Double.parseDouble(max); | ||
| if (value.getValueType() == JsonValue.ValueType.ARRAY && value.asJsonArray().size() > bound) { | ||
| errors.add(MESSAGES.maxItems(meta.getPath(), bound, value.asJsonArray().size())); | ||
| } | ||
|
|
||
| private void validateRuleMinLength(final ParameterMeta meta, final JsonValue value, | ||
| final Map<String, String> metadata) { | ||
| final String min = metadata.get("tcomp::validation::minLength"); | ||
| if (min != null) { | ||
| final double bound = Double.parseDouble(min); | ||
| if (value.getValueType() == JsonValue.ValueType.STRING) { | ||
| final String val = ((JsonString) value).getString(); | ||
| if (val.length() < bound) { | ||
| errors.add(MESSAGES.minLength(meta.getPath(), bound, val.length())); | ||
| } | ||
| } | ||
| } | ||
| { | ||
| final String unique = metadata.get("tcomp::validation::uniqueItems"); | ||
| if (unique != null) { | ||
| if (value.getValueType() == JsonValue.ValueType.ARRAY) { | ||
| final JsonArray array = value.asJsonArray(); | ||
| if (new HashSet<>(array).size() != array.size()) { | ||
| errors.add(MESSAGES.uniqueItems(meta.getPath())); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private void validateRuleMax(final ParameterMeta meta, final JsonValue value, | ||
| final Map<String, String> metadata) { | ||
| final String max = metadata.get("tcomp::validation::max"); | ||
| if (max != null) { | ||
| final double bound = Double.parseDouble(max); | ||
| if (value.getValueType() == JsonValue.ValueType.NUMBER | ||
| && ((JsonNumber) value).doubleValue() > bound) { | ||
| errors.add(MESSAGES.max(meta.getPath(), bound, ((JsonNumber) value).doubleValue())); | ||
| } | ||
| } | ||
| { | ||
| final String pattern = metadata.get("tcomp::validation::pattern"); | ||
| if (pattern != null && value.getValueType() == JsonValue.ValueType.STRING) { | ||
| final String val = ((JsonString) value).getString(); | ||
| if (!new JavascriptRegex(pattern).test((CharSequence) val)) { | ||
| errors.add(MESSAGES.pattern(meta.getPath(), pattern)); | ||
| } | ||
| } | ||
|
|
||
| private void validateRuleMin(final ParameterMeta meta, final JsonValue value, | ||
| final Map<String, String> metadata) { | ||
| final String min = metadata.get("tcomp::validation::min"); | ||
| if (min != null) { | ||
| final double bound = Double.parseDouble(min); | ||
| if (value.getValueType() == JsonValue.ValueType.NUMBER | ||
| && ((JsonNumber) value).doubleValue() < bound) { | ||
| errors.add(MESSAGES.min(meta.getPath(), bound, ((JsonNumber) value).doubleValue())); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private static boolean isRequiredAndMissingWithoutDefault(final ParameterMeta meta, | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It lacks one use case: when the default value is an empty string. In such case, the default value is considered as irrelevant
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in |
||
| final JsonValue value) { | ||
| // an empty-string default value is considered as irrelevant, so it does not | ||
| // suppress the required check - QTDI-2489 | ||
| final String defaultValue = meta.getMetadata().get("tcomp::ui::defaultvalue::value"); | ||
| return Boolean.parseBoolean(meta.getMetadata().get("tcomp::validation::required")) | ||
| && value == JsonValue.NULL | ||
| && (defaultValue == null || defaultValue.isEmpty()); | ||
| } | ||
|
|
||
| private void throwIfFailed() { | ||
| if (!errors.isEmpty()) { | ||
| throw new IllegalArgumentException("- " + String.join("\n- ", errors)); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is the fix: required rule fails if there is no default value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Acknowledged — this is a self-annotation explaining the original Round 0 guard. No further code change needed here.