From e6bea18abd1a1b4ddf7203508832e6a3f9380598 Mon Sep 17 00:00:00 2001
From: Jim Hahn <jrh3@att.com>
Date: Tue, 5 Jan 2021 11:11:26 -0500
Subject: 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>
---
 .../onap/policy/models/base/PfValidatorTest.java   | 226 ++++++++++++++
 .../org/onap/policy/models/base/ValidatedTest.java | 335 ++-------------------
 2 files changed, 254 insertions(+), 307 deletions(-)
 create mode 100644 models-base/src/test/java/org/onap/policy/models/base/PfValidatorTest.java

(limited to 'models-base/src/test/java/org/onap')

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;
-- 
cgit