diff options
author | Jim Hahn <jrh3@att.com> | 2021-01-05 11:11:26 -0500 |
---|---|---|
committer | Jim Hahn <jrh3@att.com> | 2021-01-06 15:59:14 -0500 |
commit | e6bea18abd1a1b4ddf7203508832e6a3f9380598 (patch) | |
tree | 90b8ae9fde32efcfb2f4662bcf2b87e4c430de60 /models-base/src | |
parent | f2b0318f53abf9f2345a5cdca74f3dd635aa9b60 (diff) |
Use annotations on parameterized types
Updated the code to place validation annotations directly on the
annotated types instead of using the @Items and @Entries annotations.
Also added/updated junits for validation code.
Issue-ID: POLICY-2648
Change-Id: Ia535da07a38cec77a74c5c3215b5ae784d7a4e1a
Signed-off-by: Jim Hahn <jrh3@att.com>
Diffstat (limited to 'models-base/src')
8 files changed, 282 insertions, 719 deletions
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfModel.java b/models-base/src/main/java/org/onap/policy/models/base/PfModel.java index 82b8f93f6..bdd652a92 100644 --- a/models-base/src/main/java/org/onap/policy/models/base/PfModel.java +++ b/models-base/src/main/java/org/onap/policy/models/base/PfModel.java @@ -1,7 +1,7 @@ /*- * ============LICENSE_START======================================================= * Copyright (C) 2019 Nordix Foundation. - * Modifications Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -159,7 +159,7 @@ public abstract class PfModel extends PfConcept { private void validateArtifactKeyInModel(final PfConceptKey artifactKey, final Set<PfConceptKey> artifactKeySet, final BeanValidationResult result) { - result.addResult(validateKeyNotNull(KEYS_TOKEN, artifactKey)); + validateKeyNotNull(result, KEYS_TOKEN, artifactKey); BeanValidationResult result2 = new BeanValidationResult(KEYS_TOKEN, artifactKey); diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfValidator.java b/models-base/src/main/java/org/onap/policy/models/base/PfValidator.java index c4e46e0b5..cbe9c2ca7 100644 --- a/models-base/src/main/java/org/onap/policy/models/base/PfValidator.java +++ b/models-base/src/main/java/org/onap/policy/models/base/PfValidator.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,16 +20,12 @@ package org.onap.policy.models.base; -import java.util.Map; import org.onap.policy.common.parameters.BeanValidationResult; import org.onap.policy.common.parameters.BeanValidator; -import org.onap.policy.common.parameters.EntryValidator; import org.onap.policy.common.parameters.ObjectValidationResult; import org.onap.policy.common.parameters.ValidationResult; import org.onap.policy.common.parameters.ValidationStatus; import org.onap.policy.common.parameters.ValueValidator; -import org.onap.policy.models.base.validation.annotations.PfEntries; -import org.onap.policy.models.base.validation.annotations.PfItems; import org.onap.policy.models.base.validation.annotations.PfMin; import org.onap.policy.models.base.validation.annotations.VerifyKey; @@ -39,8 +35,6 @@ public class PfValidator extends BeanValidator { protected void addValidators(ValueValidator validator) { super.addValidators(validator); - validator.addAnnotation(PfItems.class, this::verCollection); - validator.addAnnotation(PfEntries.class, this::verMap); validator.addAnnotation(VerifyKey.class, this::verKey); validator.addAnnotation(PfMin.class, this::verPfMin); } @@ -69,26 +63,6 @@ public class PfValidator extends BeanValidator { } /** - * Validates the items in a Map. - * - * @param result where to add the validation result - * @param fieldName name of the field containing the collection - * @param annot validation annotations for individual entries - * @param value value to be verified - * @return {@code true} if the next check should be performed, {@code false} otherwise - */ - public boolean verMap(BeanValidationResult result, String fieldName, PfEntries annot, Object value) { - - if (!(value instanceof Map)) { - return true; - } - - EntryValidator entryValidator = makeEntryValidator(annot.key(), annot.value()); - - return verMap(result, fieldName, entryValidator, value); - } - - /** * Invokes the value's {@link Validated#validate(String) validate()} method, if the * value is of type {@link Validated}. */ @@ -96,7 +70,14 @@ public class PfValidator extends BeanValidator { public boolean verCascade(BeanValidationResult result, String fieldName, Object value) { if (value instanceof Validated) { ValidationResult result2 = ((Validated) value).validate(fieldName); - result.addResult(result2); + if (result2 == null) { + return true; + } + + if (!result2.isClean()) { + result.addResult(result2); + } + return result2.isValid(); } diff --git a/models-base/src/main/java/org/onap/policy/models/base/Validated.java b/models-base/src/main/java/org/onap/policy/models/base/Validated.java index 2c059ba4b..5ec6ab7f7 100644 --- a/models-base/src/main/java/org/onap/policy/models/base/Validated.java +++ b/models-base/src/main/java/org/onap/policy/models/base/Validated.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,14 +20,7 @@ package org.onap.policy.models.base; -import com.google.re2j.Pattern; -import java.util.Collection; -import java.util.Map; -import java.util.Map.Entry; -import java.util.function.BiFunction; -import java.util.function.Function; import lombok.NonNull; -import org.apache.commons.lang3.StringUtils; import org.onap.policy.common.parameters.BeanValidationResult; import org.onap.policy.common.parameters.ObjectValidationResult; import org.onap.policy.common.parameters.ValidationResult; @@ -84,276 +77,44 @@ public class Validated { } /** - * Validates a value, if is not {@code null}, by invoking it's validate() method. - * - * @param result where to put the result - * @param fieldName name of the field containing the value - * @param value the field's value - */ - public static void validateOptional(@NonNull BeanValidationResult result, @NonNull String fieldName, - Validated value) { - if (value != null) { - result.addResult(value.validate(fieldName)); - } - } - - /** - * Validates that a value is not {@code null}. If the value is a subclass of this - * class, then it's {@link #validate(String)} method is invoked, too. - * - * @param fieldName name of the field containing the value - * @param value the field's value - * @return a result, or {@code null} - */ - public static ValidationResult validateNotNull(@NonNull String fieldName, Object value) { - if (value == null) { - return new ObjectValidationResult(fieldName, value, ValidationStatus.INVALID, IS_NULL); - } - - if (value instanceof Validated) { - return ((Validated) value).validate(fieldName); - } - - return null; - } - - /** - * Validates that a value is not "blank" (i.e., empty). value. - * - * @param fieldName name of the field containing the value - * @param value the field's value - * @param checkNull {@code true} if to validate that the value is not {@code null} - * @return a result, or {@code null} - */ - public static ValidationResult validateNotBlank(@NonNull String fieldName, String value, boolean checkNull) { - if (value == null && !checkNull) { - return null; - } - - if (StringUtils.isBlank(value)) { - return new ObjectValidationResult(fieldName, value, ValidationStatus.INVALID, IS_BLANK); - } - - return null; - } - - /** - * Validates that a value matches regular expression. - * - * @param fieldName name of the field containing the value - * @param value the field's value - * @param pattern regular expression to be matched - * @return a result, or {@code null} - */ - public static ValidationResult validateRegex(@NonNull String fieldName, String value, @NonNull String pattern) { - if (value == null) { - return makeNullResult(fieldName, value); - } - - if (!Pattern.matches(pattern, value)) { - return new ObjectValidationResult(fieldName, value, ValidationStatus.INVALID, - "does not match regular expression " + pattern); - } - - return null; - } - - /** * Validates a key, ensuring that it isn't null and that it's structurally sound. * + * @param result where to add the validation result * @param fieldName name of the field containing the key * @param key the field's value - * @return a result, or {@code null} */ - public static ValidationResult validateKeyNotNull(@NonNull String fieldName, PfKey key) { + public static void validateKeyNotNull(BeanValidationResult result, @NonNull String fieldName, PfKey key) { if (key == null) { - return new ObjectValidationResult(fieldName, key, ValidationStatus.INVALID, IS_A_NULL_KEY); + result.addResult(new ObjectValidationResult(fieldName, key, ValidationStatus.INVALID, IS_A_NULL_KEY)); + return; } if (key.isNullKey()) { - return new ObjectValidationResult(fieldName, key.getId(), ValidationStatus.INVALID, IS_A_NULL_KEY); + result.addResult(new ObjectValidationResult(fieldName, key.getId(), ValidationStatus.INVALID, + IS_A_NULL_KEY)); + return; } - return key.validate(fieldName); + result.addResult(key.validate(fieldName)); } /** * Validates a key's version, ensuring that it isn't null. * + * @param result where to add the validation result * @param fieldName name of the field containing the key * @param key the field's value - * @return a result, or {@code null} */ - public static BeanValidationResult validateKeyVersionNotNull(@NonNull String fieldName, PfConceptKey key) { + public static void validateKeyVersionNotNull(BeanValidationResult result, @NonNull String fieldName, + PfConceptKey key) { if (key != null && key.isNullVersion()) { - BeanValidationResult result = new BeanValidationResult(fieldName, key); - result.addResult(makeNullResult(PfKeyImpl.VERSION_TOKEN, key.getVersion())); - return result; - } - - return null; - } - - /** - * Generates a function to validate that a value is not below a minimum. - * - * @param min minimum value allowed - * @param allowedValue {@code null} or an allowed value outside the range - * @param checkRef {@code true} to generate an error if the value is {@code null} - * @return a function to validate that a value is not below a minimum - */ - public static BiFunction<String, Integer, ValidationResult> validateMin(int min, Integer allowedValue, - boolean checkRef) { - return (name, value) -> validateMin(name, value, min, allowedValue, checkRef); - } - - /** - * Validates that a value is not below a minimum. - * - * @param fieldName name of the field containing the key - * @param value the field's value - * @param min minimum value allowed - * @param allowedValue {@code null} or an allowed value outside the range - * @param checkRef {@code true} to generate an error if the value is {@code null} - * @return a result, or {@code null} - */ - public static ValidationResult validateMin(@NonNull String fieldName, Integer value, int min, Integer allowedValue, - boolean checkRef) { - if (value == null) { - if (checkRef) { - return makeNullResult(fieldName, value); - } - - return null; - } - - if (value < min && !value.equals(allowedValue)) { - return new ObjectValidationResult(fieldName, value, ValidationStatus.INVALID, - "is below the minimum value: " + min); - } - - return null; - } - - /** - * Validates the items in a list. - * - * @param result where to add the results - * @param fieldName name of the field containing the list - * @param list the field's list (may be {@code null}) - * @param checker function to validate in individual item in the list - */ - public static <T> void validateList(@NonNull BeanValidationResult result, @NonNull String fieldName, - Collection<T> list, @NonNull BiFunction<String, T, ValidationResult> checker) { - if (list == null) { - return; - } - - BeanValidationResult result2 = new BeanValidationResult(fieldName, list); - - int count = 0; - for (T value : list) { - result2.addResult(checker.apply(String.valueOf(count++), value)); - } - - if (!result2.isClean()) { + BeanValidationResult result2 = new BeanValidationResult(fieldName, key); + result2.addResult(makeNullResult(PfKeyImpl.VERSION_TOKEN, key.getVersion())); result.addResult(result2); } } /** - * Validates the items in a map. - * - * @param result where to add the results - * @param fieldName name of the field containing the list - * @param map the field's map (may be {@code null}) - * @param checker function to validate in individual item in the list - */ - public static <T> void validateMap(@NonNull BeanValidationResult result, @NonNull String fieldName, - Map<String, T> map, @NonNull Function<Map.Entry<String, T>, ValidationResult> checker) { - if (map == null) { - return; - } - - BeanValidationResult result2 = new BeanValidationResult(fieldName, map); - - for (Entry<String, T> entry : map.entrySet()) { - result2.addResult(checker.apply(entry)); - } - - if (!result2.isClean()) { - result.addResult(result2); - } - } - - /** - * Validates a Map entry, ensuring that neither the key nor the value are "blank" - * (i.e., empty or {@code null}). - * - * @param entry entry to be validated - * @return a result, or {@code null} - */ - public static BeanValidationResult validateEntryNotBlankNotBlank(Map.Entry<String, String> entry) { - BeanValidationResult result = new BeanValidationResult("" + entry.getKey(), entry.getKey()); - - if (StringUtils.isBlank(entry.getKey())) { - Validated.addResult(result, KEY_TOKEN, entry.getKey(), IS_BLANK); - } - - if (StringUtils.isBlank(entry.getValue())) { - Validated.addResult(result, VALUE_TOKEN, entry.getValue(), IS_BLANK); - } - - return (result.isClean() ? null : result); - } - - /** - * Validates a Map entry, ensuring that the key is not "blank" (i.e., empty or - * {@code null}) and the value is not {@code null}. - * - * @param entry entry to be validated - * @return a result, or {@code null} - */ - public static BeanValidationResult validateEntryNotBlankNotNull(Map.Entry<String, String> entry) { - BeanValidationResult result = new BeanValidationResult("" + entry.getKey(), entry.getKey()); - - if (StringUtils.isBlank(entry.getKey())) { - Validated.addResult(result, KEY_TOKEN, entry.getKey(), IS_BLANK); - } - - if (entry.getValue() == null) { - result.addResult(makeNullResult(VALUE_TOKEN, entry.getValue())); - } - - return (result.isClean() ? null : result); - } - - /** - * Validates a Map entry, ensuring that neither the key nor the value are - * {@code null}. If the value is a subclass of this class, then it's - * {@link #validate(String)} method is invoked. - * - * @param entry entry to be validated - * @return a result, or {@code null} - */ - public static <V> BeanValidationResult validateEntryValueNotNull(Map.Entry<String, V> entry) { - BeanValidationResult result = new BeanValidationResult("" + entry.getKey(), entry.getKey()); - - if (entry.getKey() == null) { - result.addResult(makeNullResult(KEY_TOKEN, entry.getKey())); - } - - V value = entry.getValue(); - if (value == null) { - result.addResult(makeNullResult(VALUE_TOKEN, value)); - } else if (value instanceof Validated) { - result.addResult(((Validated) value).validate(VALUE_TOKEN)); - } - - return (result.isClean() ? null : result); - } - - /** * Gets a key's ID, if the value is a {@link PfKey}. * * @param value value from which to get the ID diff --git a/models-base/src/main/java/org/onap/policy/models/base/validation/annotations/PfEntries.java b/models-base/src/main/java/org/onap/policy/models/base/validation/annotations/PfEntries.java deleted file mode 100644 index f3726003b..000000000 --- a/models-base/src/main/java/org/onap/policy/models/base/validation/annotations/PfEntries.java +++ /dev/null @@ -1,45 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.models.base.validation.annotations; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Validations on entries within a Map. - */ -@Retention(RUNTIME) -@Target(FIELD) -public @interface PfEntries { - - /** - * Validations to perform on each entry's key. - */ - PfItems key(); - - /** - * Validations to perform on each entry's value. - */ - PfItems value(); -} diff --git a/models-base/src/main/java/org/onap/policy/models/base/validation/annotations/PfItems.java b/models-base/src/main/java/org/onap/policy/models/base/validation/annotations/PfItems.java deleted file mode 100644 index 363cf6f34..000000000 --- a/models-base/src/main/java/org/onap/policy/models/base/validation/annotations/PfItems.java +++ /dev/null @@ -1,82 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.models.base.validation.annotations; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; -import org.intellij.lang.annotations.Pattern; -import org.onap.policy.common.parameters.annotations.Max; -import org.onap.policy.common.parameters.annotations.Min; -import org.onap.policy.common.parameters.annotations.NotBlank; -import org.onap.policy.common.parameters.annotations.NotNull; -import org.onap.policy.common.parameters.annotations.Valid; - -/** - * Validations on individual items, typically within a collection. - */ -@Retention(RUNTIME) -@Target(FIELD) -public @interface PfItems { - - /** - * Validates the item is not {@code null}. - */ - NotNull[] notNull() default {}; - - /** - * Validates the item is not blank. - */ - NotBlank[] notBlank() default {}; - - /** - * Validates the item matches a regular expression. - */ - Pattern[] pattern() default {}; - - /** - * Validates the item is not greater than a certain value. - */ - Max[] max() default {}; - - /** - * Validates the item is not less than a certain value. - */ - Min[] min() default {}; - - /** - * Validates the item is not less than a certain value. - */ - PfMin[] pfMin() default {}; - - /** - * Validates the item is valid, using a {@link BeanValidator}. - */ - Valid[] valid() default {}; - - /** - * Validates a key. - */ - VerifyKey[] key() default {}; - -} diff --git a/models-base/src/main/java/org/onap/policy/models/base/validation/annotations/PfMin.java b/models-base/src/main/java/org/onap/policy/models/base/validation/annotations/PfMin.java index 71f001848..8b7190a6e 100644 --- a/models-base/src/main/java/org/onap/policy/models/base/validation/annotations/PfMin.java +++ b/models-base/src/main/java/org/onap/policy/models/base/validation/annotations/PfMin.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ package org.onap.policy.models.base.validation.annotations; import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.TYPE_USE; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Retention; @@ -30,7 +31,7 @@ import java.lang.annotation.Target; * Same as the "Min" annotation, but allows an extra value that is not in the range. */ @Retention(RUNTIME) -@Target(FIELD) +@Target({FIELD, TYPE_USE}) public @interface PfMin { /** diff --git a/models-base/src/test/java/org/onap/policy/models/base/PfValidatorTest.java b/models-base/src/test/java/org/onap/policy/models/base/PfValidatorTest.java new file mode 100644 index 000000000..812916e3c --- /dev/null +++ b/models-base/src/test/java/org/onap/policy/models/base/PfValidatorTest.java @@ -0,0 +1,226 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.models.base; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.concurrent.atomic.AtomicBoolean; +import javax.validation.Valid; +import lombok.Getter; +import lombok.NonNull; +import org.junit.Before; +import org.junit.Test; +import org.onap.policy.common.parameters.BeanValidationResult; +import org.onap.policy.common.parameters.annotations.NotNull; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.models.base.validation.annotations.PfMin; +import org.onap.policy.models.base.validation.annotations.VerifyKey; + +public class PfValidatorTest { + private static final String KEY_FIELD = "key"; + + private static final String STRING_VALUE = "abc"; + + private PfValidator validator; + + @Before + public void setUp() { + validator = new PfValidator(); + } + + @Test + public void testAddValidatorsValueValidator() { + // verify that standard annotations work + StdAnnotation data = new StdAnnotation(); + data.strValue = STRING_VALUE; + assertThat(validator.validateTop("", data).getResult()).isNull(); + + data.strValue = null; + assertThat(validator.validateTop("", data).getResult()).contains("strValue", "null"); + } + + @Test + public void testVerPfMin() { + PfMinChecker data = new PfMinChecker(); + data.intValue = 10; + assertThat(validator.validateTop("", data).getResult()).isNull(); + + data.intValue = -2; + assertThat(validator.validateTop("", data).getResult()).isNull(); + + data.intValue = null; + assertThat(validator.validateTop("", data).getResult()).isNull(); + + data.intValue = STRING_VALUE; + assertThat(validator.validateTop("", data).getResult()).isNull(); + + data.intValue = -1; + assertThat(validator.validateTop("", data).getResult()).contains("intValue", "-1"); + } + + @Test + public void testVerCascadeBeanValidationResultStringObject() { + CascadeChecker checker = new CascadeChecker(); + checker.plain = new StdAnnotation(); + + // valid + checker.plain.strValue = STRING_VALUE; + BeanValidationResult result = new BeanValidationResult("", this); + assertThat(validator.verCascade(result, "", checker)).isTrue(); + + // invalid + checker.plain.strValue = null; + + result = new BeanValidationResult("", this); + assertThat(validator.verCascade(result, "", checker.plain)).isFalse(); + assertThat(result.getResult()).contains("null"); + + result = new BeanValidationResult("", this); + assertThat(validator.verCascade(result, "", checker)).isFalse(); + assertThat(result.getResult()).contains("null").doesNotContain("plain"); + + // validator returns null result - should be treated as valid + checker = new CascadeChecker() { + @Override + public BeanValidationResult validate(@NonNull String fieldName) { + return null; + } + }; + checker.plain = new StdAnnotation(); + result = new BeanValidationResult("", this); + assertThat(validator.verCascade(result, "", checker)).isTrue(); + } + + @Test + public void testVerKey() throws CoderException { + FullKeyAnnot data = new FullKeyAnnot(); + + // not a key + data.key = STRING_VALUE; + assertThat(validator.validateTop("", data).getResult()).isNull(); + + // null key + data.key = new PfConceptKey(); + assertThat(validator.validateTop("", data).getResult()) + .contains(KEY_FIELD, "NULL:0.0.0", Validated.IS_A_NULL_KEY).doesNotContain("name", "version"); + + // invalid version - should invoke verCascade() which will invoke key.validate() + data.key = new StandardCoder().decode("{'name':'abc', 'version':'xyzzy'}".replace('\'', '"'), + PfConceptKey.class); + assertThat(validator.validateTop("", data).getResult()) + .contains(KEY_FIELD, "version", "xyzzy", "regular expression").doesNotContain("name"); + + // not a PfKeyImpl - should not check individual fields + PfKey pfkey = mock(PfKey.class); + data.key = pfkey; + assertThat(validator.validateTop("", data).getResult()).isNull(); + + when(pfkey.isNullKey()).thenReturn(true); + assertThat(validator.validateTop("", data).getResult()).contains(KEY_FIELD, Validated.IS_A_NULL_KEY); + + // null name + data.key = new PfConceptKey(PfKey.NULL_KEY_NAME, "2.3.4"); + assertThat(validator.validateTop("", data).getResult()).contains(KEY_FIELD, "name", "null") + .doesNotContain("version", "2.3.4"); + + // null version + data.key = new PfConceptKey(STRING_VALUE, PfKey.NULL_KEY_VERSION); + assertThat(validator.validateTop("", data).getResult()).contains(KEY_FIELD, "version", "null") + .doesNotContain("name", STRING_VALUE); + + // null name, invalid version - should get two messages + data.key = new StandardCoder().decode("{'name':'NULL', 'version':'xyzzy'}".replace('\'', '"'), + PfConceptKey.class); + assertThat(validator.validateTop("", data).getResult()).contains(KEY_FIELD, "name", "null", "version", "xyzzy", + "regular expression"); + + /* + * Tests with all flags set to "false" (i.e., no validations). + */ + + EmptyKeyAnnot data2 = new EmptyKeyAnnot(); + + // build a key that is totally invalid + AtomicBoolean called = new AtomicBoolean(); + + data2.key = new PfConceptKey() { + private static final long serialVersionUID = 1L; + + @Override + public BeanValidationResult validate(@NonNull String fieldName) { + called.set(true); + return null; + } + }; + + // should be ok, since no validations are performed + assertThat(validator.validateTop("", data2).getResult()).isNull(); + assertThat(called.get()).isFalse(); + } + + @Test + public void testXlateObject() { + assertThat(validator.xlate(null)).isNull(); + assertThat(validator.xlate("hello")).isEqualTo("hello"); + + PfConceptKey key = new PfConceptKey("hello", "1.2.3"); + assertThat(validator.xlate(key)).isEqualTo("hello:1.2.3"); + } + + public static class StdAnnotation { + @Getter + @NotNull + private String strValue; + } + + public static class PfMinChecker { + @Getter + @PfMin(value = 5, allowed = -2) + private Object intValue; + } + + public static class CascadeChecker extends Validated { + @Getter + @Valid + private StdAnnotation plain; + + @Override + public BeanValidationResult validate(@NonNull String fieldName) { + // directly validates "plain" + return new PfValidator().validateTop(fieldName, plain); + } + } + + public static class FullKeyAnnot { + @Getter + @VerifyKey(keyNotNull = true, nameNotNull = true, versionNotNull = true, valid = true) + private Object key; + } + + public static class EmptyKeyAnnot { + @Getter + @VerifyKey(keyNotNull = false, nameNotNull = false, versionNotNull = false, valid = false) + private PfKey key; + } +} diff --git a/models-base/src/test/java/org/onap/policy/models/base/ValidatedTest.java b/models-base/src/test/java/org/onap/policy/models/base/ValidatedTest.java index dab28f636..91fa301f9 100644 --- a/models-base/src/test/java/org/onap/policy/models/base/ValidatedTest.java +++ b/models-base/src/test/java/org/onap/policy/models/base/ValidatedTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,13 +25,7 @@ import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.BiFunction; import lombok.AllArgsConstructor; import lombok.NonNull; import org.junit.Test; @@ -51,7 +45,6 @@ public class ValidatedTest { private static final String OTHER = "other text"; private static final String NAME = "myKey"; private static final String VERSION = "1.0.0"; - private static final String BLANKS = "\t \n"; @Test public void testAddResult() { @@ -84,91 +77,24 @@ public class ValidatedTest { } @Test - public void testValidateOptional() { + public void testValidateKeyNotNull() throws CoderException { BeanValidationResult result = new BeanValidationResult("", this); - Validated.validateOptional(result, MY_FIELD, null); - assertTrue(result.isClean()); - - Validated.validateOptional(result, MY_FIELD, new MyString(TEXT)); - assertTrue(result.isClean()); - - Validated.validateOptional(result, MY_FIELD, new MyString(OTHER)); - assertThat(result.getResult()).contains(MY_FIELD).contains(OTHER).contains(NOT_SAME); - - assertThatThrownBy(() -> Validated.validateOptional(null, MY_FIELD, new MyString(TEXT))) - .isInstanceOf(NullPointerException.class); - - assertThatThrownBy(() -> Validated.validateOptional(result, null, new MyString(TEXT))) - .isInstanceOf(NullPointerException.class); - - assertThatCode(() -> Validated.validateOptional(result, MY_FIELD, null)).doesNotThrowAnyException(); - } - - @Test - public void testValidateNotNull() { - assertThat(Validated.validateNotNull(MY_FIELD, TEXT)).isNull(); - - assertThat(Validated.validateNotNull(MY_FIELD, null).getResult()).contains(MY_FIELD) - .contains(Validated.IS_NULL); - - // should invoke the value's validate() method, which should return success - assertThat(Validated.validateNotNull(MY_FIELD, new MyString(TEXT))).isNull(); - - // should invoke the value's validate() method, which should return failure - assertThat(Validated.validateNotNull(MY_FIELD, new MyString(OTHER)).getResult()).contains(MY_FIELD) - .contains(NOT_SAME); - - assertThatThrownBy(() -> Validated.validateNotNull(null, TEXT)).isInstanceOf(NullPointerException.class); - - assertThatCode(() -> Validated.validateNotNull(MY_FIELD, null)).doesNotThrowAnyException(); - } - - @Test - public void testValidateNotBlank() { - assertThat(Validated.validateNotBlank(MY_FIELD, TEXT, false)).isNull(); - assertThat(Validated.validateNotBlank(MY_FIELD, TEXT, true)).isNull(); - - assertThat(Validated.validateNotBlank(MY_FIELD, null, false)).isNull(); - assertThat(Validated.validateNotBlank(MY_FIELD, null, true).getResult()).contains(MY_FIELD) - .contains(Validated.IS_BLANK); - - assertThat(Validated.validateNotBlank(MY_FIELD, "", false).getResult()).contains(MY_FIELD) - .contains(Validated.IS_BLANK); - assertThat(Validated.validateNotBlank(MY_FIELD, "", true).getResult()).contains(MY_FIELD) - .contains(Validated.IS_BLANK); - - assertThatThrownBy(() -> Validated.validateNotBlank(null, TEXT, false)) - .isInstanceOf(NullPointerException.class); - - assertThatCode(() -> Validated.validateNotBlank(MY_FIELD, null, false)).doesNotThrowAnyException(); - } - - @Test - public void testValidateRegex() { - assertThat(Validated.validateRegex(MY_FIELD, "hello", ".*ll.*")).isNull(); - - assertThat(Validated.validateRegex(MY_FIELD, "hello", "[x-z]").getResult()).contains(MY_FIELD).contains("hello") - .contains("does not match regular expression [x-z]"); - - assertThatThrownBy(() -> Validated.validateRegex(null, "hello", "ll")).isInstanceOf(NullPointerException.class); - - assertThatCode(() -> Validated.validateRegex(MY_FIELD, null, "ll")).doesNotThrowAnyException(); + Validated.validateKeyNotNull(result, MY_FIELD, new PfConceptKey(NAME, VERSION)); + assertThat(result.getResult()).isNull(); - assertThatThrownBy(() -> Validated.validateRegex(MY_FIELD, "hello", null)) - .isInstanceOf(NullPointerException.class); - } + result = new BeanValidationResult("", this); + Validated.validateKeyNotNull(result, MY_FIELD, new PfConceptKey(NAME, PfConceptKey.NULL_KEY_VERSION)); + assertThat(result.getResult()).isNull(); - @Test - public void testValidateKeyNotNull() throws CoderException { - assertThat(Validated.validateKeyNotNull(MY_FIELD, new PfConceptKey(NAME, VERSION)).getResult()).isNull(); - assertThat(Validated.validateKeyNotNull(MY_FIELD, new PfConceptKey(NAME, PfConceptKey.NULL_KEY_VERSION)) - .getResult()).isNull(); - assertThat(Validated.validateKeyNotNull(MY_FIELD, new PfConceptKey(PfConceptKey.NULL_KEY_NAME, VERSION)) - .getResult()).isNull(); + result = new BeanValidationResult("", this); + Validated.validateKeyNotNull(result, MY_FIELD, new PfConceptKey(PfConceptKey.NULL_KEY_NAME, VERSION)); + assertThat(result.getResult()).isNull(); // key is null - assertThat(Validated.validateKeyNotNull(MY_FIELD, new PfConceptKey()).getResult()).contains(MY_FIELD) - .doesNotContain("\"name\"").doesNotContain("\"version\"").contains(Validated.IS_A_NULL_KEY); + result = new BeanValidationResult("", this); + Validated.validateKeyNotNull(result, MY_FIELD, new PfConceptKey()); + assertThat(result.getResult()).contains(MY_FIELD, Validated.IS_A_NULL_KEY) + .doesNotContain("\"name\"", "\"version\""); /* * Key is not null, but key.validate() should fail due to an invalid version. @@ -177,237 +103,38 @@ public class ValidatedTest { */ PfConceptKey key = new StandardCoder().decode("{'name':'myKey','version':'bogus'}".replace('\'', '"'), PfConceptKey.class); - assertThat(Validated.validateKeyNotNull(MY_FIELD, key).getResult()).contains(MY_FIELD).contains("version") - .contains("does not match regular expression"); - - // null parameter tests - assertThatThrownBy(() -> Validated.validateKeyNotNull(null, new PfConceptKey())) - .isInstanceOf(NullPointerException.class); - - assertThatCode(() -> Validated.validateKeyNotNull(MY_FIELD, null)).doesNotThrowAnyException(); - } - - @Test - public void testValidateKeyVersionNotNull() { - assertThat(Validated.validateKeyVersionNotNull(MY_FIELD, null)).isNull(); - - assertThat(Validated.validateKeyVersionNotNull(MY_FIELD, new PfConceptKey(NAME, VERSION))).isNull(); - - assertThat(Validated.validateKeyVersionNotNull(MY_FIELD, new PfConceptKey(NAME, PfConceptKey.NULL_KEY_VERSION)) - .getResult()).contains(MY_FIELD).contains("version").contains(Validated.IS_NULL); - - assertThatThrownBy(() -> Validated.validateKeyVersionNotNull(null, new PfConceptKey())) - .isInstanceOf(NullPointerException.class); - - assertThatCode(() -> Validated.validateKeyVersionNotNull(MY_FIELD, null)).doesNotThrowAnyException(); - } - - @Test - public void testValidateMinIntIntegerBoolean_testValidateMinStringIntegerIntIntegerBoolean() { - /* - * No "special" value, don't check the reference. - */ - BiFunction<String, Integer, ValidationResult> func = Validated.validateMin(10, null, false); - assertThat(func.apply(MY_FIELD, null)).isNull(); - - // exact match - assertThat(func.apply(MY_FIELD, 10)).isNull(); - - assertThat(func.apply(MY_FIELD, 20)).isNull(); - - assertThat(func.apply(MY_FIELD, 9).getResult()).contains(MY_FIELD).contains("9") - .contains("is below the minimum value: 10"); - - /* - * "special" value, don't check the reference. - */ - func = Validated.validateMin(10, 7, false); - assertThat(func.apply(MY_FIELD, null)).isNull(); - - // exact match - assertThat(func.apply(MY_FIELD, 10)).isNull(); - - assertThat(func.apply(MY_FIELD, 20)).isNull(); - - // special value - should be ok - assertThat(func.apply(MY_FIELD, 7)).isNull(); - - assertThat(func.apply(MY_FIELD, 9).getResult()).contains(MY_FIELD).contains("9") - .contains("is below the minimum value: 10"); - - /* - * Check the reference (i.e., generate an error if the value is null). - */ - func = Validated.validateMin(10, null, true); - assertThat(func.apply(MY_FIELD, null).getResult()).contains(MY_FIELD).contains(Validated.IS_NULL); - - // exact match - assertThat(func.apply(MY_FIELD, 10)).isNull(); - - assertThat(func.apply(MY_FIELD, 20)).isNull(); - - assertThat(func.apply(MY_FIELD, 9).getResult()).contains(MY_FIELD).contains("9") - .contains("is below the minimum value: 10"); - - - BiFunction<String, Integer, ValidationResult> func2 = func; - assertThatThrownBy(() -> func2.apply(null, 30)).isInstanceOf(NullPointerException.class); - - assertThatCode(() -> func2.apply(MY_FIELD, null)).doesNotThrowAnyException(); - } - - @Test - public void testValidateList() { - BeanValidationResult result = new BeanValidationResult("", this); - Validated.validateList(result, MY_FIELD, null, Validated::validateNotNull); - assertThat(result.getResult()).isNull(); - result = new BeanValidationResult("", this); - Validated.validateList(result, MY_FIELD, List.of(TEXT, OTHER), Validated::validateNotNull); - assertThat(result.getResult()).isNull(); + Validated.validateKeyNotNull(result, MY_FIELD, key); + assertThat(result.getResult()).contains(MY_FIELD, "version", "does not match regular expression"); - List<String> list = new ArrayList<>(); - list.add(TEXT); - list.add(null); - list.add(OTHER); - list.add(null); - result = new BeanValidationResult("", this); - Validated.validateList(result, MY_FIELD, list, Validated::validateNotNull); - assertThat(result.getResult()).doesNotContain("0").contains("1").doesNotContain("2").contains("3") - .contains(Validated.IS_NULL); + BeanValidationResult result2 = new BeanValidationResult("", this); - BeanValidationResult result2 = result; - assertThatThrownBy(() -> Validated.validateList(null, MY_FIELD, List.of(), Validated::validateNotNull)) - .isInstanceOf(NullPointerException.class); - - assertThatThrownBy(() -> Validated.validateList(result2, null, List.of(), Validated::validateNotNull)) + // null parameter tests + assertThatThrownBy(() -> Validated.validateKeyNotNull(result2, null, new PfConceptKey())) .isInstanceOf(NullPointerException.class); - assertThatCode(() -> Validated.validateList(result2, MY_FIELD, null, Validated::validateNotNull)) - .doesNotThrowAnyException(); - - assertThatThrownBy(() -> Validated.validateList(result2, MY_FIELD, List.of(), null)) - .isInstanceOf(NullPointerException.class); + assertThatCode(() -> Validated.validateKeyNotNull(result2, MY_FIELD, null)).doesNotThrowAnyException(); } @Test - public void testValidateMap() { + public void testValidateKeyVersionNotNull() { BeanValidationResult result = new BeanValidationResult("", this); - Validated.validateMap(result, MY_FIELD, null, Validated::validateEntryNotBlankNotBlank); + Validated.validateKeyVersionNotNull(result, MY_FIELD, null); assertThat(result.getResult()).isNull(); result = new BeanValidationResult("", this); - Validated.validateMap(result, MY_FIELD, Map.of("abc", TEXT, "def", OTHER), - Validated::validateEntryNotBlankNotBlank); + Validated.validateKeyVersionNotNull(result, MY_FIELD, new PfConceptKey(NAME, VERSION)); assertThat(result.getResult()).isNull(); - // invalid values - Map<String, String> map = new HashMap<>(); - map.put("ghi", TEXT); - map.put("jkl", ""); - map.put("mno", OTHER); - map.put("pqr", ""); - result = new BeanValidationResult("", this); - Validated.validateMap(result, MY_FIELD, map, Validated::validateEntryNotBlankNotBlank); - assertThat(result.getResult()).doesNotContain("abc").contains("jkl").doesNotContain("mno").contains("pqr") - .contains(Q_VALUE).doesNotContain(Q_KEY).contains(Validated.IS_BLANK); - - // invalid keys - map = new HashMap<>(); - map.put("stu", TEXT); - map.put("", TEXT); - map.put("vwx", OTHER); - map.put(null, OTHER); result = new BeanValidationResult("", this); - Validated.validateMap(result, MY_FIELD, map, Validated::validateEntryNotBlankNotBlank); - assertThat(result.getResult()).doesNotContain("stu").contains("\"\"").doesNotContain("vwx").contains("null") - .contains(Q_KEY).doesNotContain(Q_VALUE).contains(Validated.IS_BLANK); + Validated.validateKeyVersionNotNull(result, MY_FIELD, new PfConceptKey(NAME, PfConceptKey.NULL_KEY_VERSION)); + assertThat(result.getResult()).contains(MY_FIELD).contains("version").contains(Validated.IS_NULL); - BeanValidationResult result2 = result; - Map<String, String> map2 = map; - assertThatThrownBy(() -> Validated.validateMap(null, MY_FIELD, map2, Validated::validateEntryNotBlankNotBlank)) + BeanValidationResult result2 = new BeanValidationResult("", this); + assertThatThrownBy(() -> Validated.validateKeyVersionNotNull(result2, null, new PfConceptKey())) .isInstanceOf(NullPointerException.class); - assertThatThrownBy(() -> Validated.validateMap(result2, null, map2, Validated::validateEntryNotBlankNotBlank)) - .isInstanceOf(NullPointerException.class); - - assertThatCode(() -> Validated.validateMap(result2, MY_FIELD, null, Validated::validateEntryNotBlankNotBlank)) - .doesNotThrowAnyException(); - - assertThatThrownBy(() -> Validated.validateMap(result2, MY_FIELD, map2, null)) - .isInstanceOf(NullPointerException.class); - } - - @Test - public void testValidateEntryNotBlankNotBlank() { - assertThat(Validated.validateEntryNotBlankNotBlank(makeEntry(TEXT, OTHER))).isNull(); - - // try invalid values for the key - assertThat(Validated.validateEntryNotBlankNotBlank(makeEntry(null, OTHER)).getResult()).contains(Q_KEY) - .contains(Validated.IS_BLANK).doesNotContain(Q_VALUE); - - assertThat(Validated.validateEntryNotBlankNotBlank(makeEntry(BLANKS, OTHER)).getResult()).contains(Q_KEY) - .contains(Validated.IS_BLANK).doesNotContain(Q_VALUE); - - // try invalid values for the value - assertThat(Validated.validateEntryNotBlankNotBlank(makeEntry(TEXT, null)).getResult()).contains(Q_VALUE) - .contains(Validated.IS_BLANK).doesNotContain(Q_KEY); - - assertThat(Validated.validateEntryNotBlankNotBlank(makeEntry(TEXT, BLANKS)).getResult()).contains(Q_VALUE) - .contains(Validated.IS_BLANK).doesNotContain(Q_KEY); - - // both invalid - assertThat(Validated.validateEntryNotBlankNotBlank(makeEntry(BLANKS, BLANKS)).getResult()).contains(Q_KEY) - .contains(Q_VALUE); - } - - @Test - public void testValidateEntryNotBlankNotNull() { - assertThat(Validated.validateEntryNotBlankNotNull(makeEntry(TEXT, OTHER))).isNull(); - - // try invalid values for the key - assertThat(Validated.validateEntryNotBlankNotNull(makeEntry(null, OTHER)).getResult()).contains(Q_KEY) - .contains(Validated.IS_BLANK).doesNotContain(Q_VALUE); - - assertThat(Validated.validateEntryNotBlankNotNull(makeEntry(BLANKS, OTHER)).getResult()).contains(Q_KEY) - .contains(Validated.IS_BLANK).doesNotContain(Q_VALUE); - - // try invalid values for the value - assertThat(Validated.validateEntryNotBlankNotNull(makeEntry(TEXT, null)).getResult()).contains(Q_VALUE) - .contains(Validated.IS_NULL).doesNotContain(Q_KEY); - - // blanks should have no impact for the value - assertThat(Validated.validateEntryNotBlankNotNull(makeEntry(TEXT, BLANKS))).isNull(); - - // both invalid - assertThat(Validated.validateEntryNotBlankNotNull(makeEntry(BLANKS, null)).getResult()).contains(Q_KEY) - .contains(Q_VALUE); - } - - @Test - public void testValidateEntryValueNotNull() { - assertThat(Validated.validateEntryValueNotNull(makeEntry(TEXT, OTHER))).isNull(); - - // blanks should have no impact - assertThat(Validated.validateEntryValueNotNull(makeEntry(BLANKS, OTHER))).isNull(); - assertThat(Validated.validateEntryNotBlankNotNull(makeEntry(TEXT, BLANKS))).isNull(); - - assertThat(Validated.validateEntryValueNotNull(makeEntry(null, OTHER)).getResult()).contains(Q_KEY) - .contains(Validated.IS_NULL).doesNotContain(Q_VALUE); - - assertThat(Validated.validateEntryValueNotNull(makeEntry(TEXT, null)).getResult()).contains(Q_VALUE) - .contains(Validated.IS_NULL).doesNotContain(Q_KEY); - - // should invoke the value's validate() method, which should return success - assertThat(Validated.validateEntryValueNotNull(makeEntry(TEXT, new MyString(TEXT)))).isNull(); - - // should invoke the value's validate() method, which should return failure - assertThat(Validated.validateEntryValueNotNull(makeEntry(TEXT, new MyString(OTHER))).getResult()) - .contains(Q_VALUE).contains(NOT_SAME).doesNotContain(Q_KEY); - - // both invalid - assertThat(Validated.validateEntryValueNotNull(makeEntry(null, null)).getResult()).contains(Q_KEY) - .contains(Q_VALUE); + assertThatCode(() -> Validated.validateKeyVersionNotNull(result2, MY_FIELD, null)).doesNotThrowAnyException(); } @Test @@ -423,12 +150,6 @@ public class ValidatedTest { assertThat(result.getResult()).contains(MY_FIELD).contains("myKey:1.0.0").contains("some message"); } - private <V> Map.Entry<String, V> makeEntry(String key, V value) { - Map<String, V> map = new HashMap<>(); - map.put(key, value); - return map.entrySet().iterator().next(); - } - @AllArgsConstructor private static class MyString extends Validated { private final String text; |