summaryrefslogtreecommitdiffstats
path: root/models-base/src/main/java
diff options
context:
space:
mode:
authorJim Hahn <jrh3@att.com>2020-12-18 19:01:52 -0500
committerJim Hahn <jrh3@att.com>2020-12-21 10:38:00 -0500
commit12fce55a66848bcc7f71430324b3a9051b8ce0d4 (patch)
treef8fdcb848f5b3bcfc07cc44f728bc51da620c6b3 /models-base/src/main/java
parent6345dce40405740dc09176c45dae03baeb939b8e (diff)
Use annotations to do validation
Modified models to use annotations instead of function calls for most field validations. Created a few new validation annotations for use within models. Per review comments: - renamed Key to VerifyKey - enhanced VerifyKey to imply "@Valid", unless disabled Issue-ID: POLICY-2648 Change-Id: I2b53f218b0a2ab1ed1f5e278816a3509f1408972 Signed-off-by: Jim Hahn <jrh3@att.com>
Diffstat (limited to 'models-base/src/main/java')
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfConceptContainer.java8
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfConceptKey.java3
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfKeyImpl.java12
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfKeyUse.java15
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfModel.java8
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfReferenceKey.java24
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfSearchableKey.java3
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfTimestampKey.java3
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/PfValidator.java160
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/Validated.java9
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/validation/annotations/PfEntries.java45
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/validation/annotations/PfItems.java82
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/validation/annotations/PfMin.java47
-rw-r--r--models-base/src/main/java/org/onap/policy/models/base/validation/annotations/VerifyKey.java57
14 files changed, 432 insertions, 44 deletions
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfConceptContainer.java b/models-base/src/main/java/org/onap/policy/models/base/PfConceptContainer.java
index 484632f7c..4c2cf0c4f 100644
--- a/models-base/src/main/java/org/onap/policy/models/base/PfConceptContainer.java
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfConceptContainer.java
@@ -47,6 +47,8 @@ import lombok.NonNull;
import org.apache.commons.lang3.StringUtils;
import org.onap.policy.common.parameters.BeanValidationResult;
import org.onap.policy.common.parameters.ValidationResult;
+import org.onap.policy.common.parameters.annotations.NotNull;
+import org.onap.policy.models.base.validation.annotations.VerifyKey;
// @formatter:off
/**
@@ -73,6 +75,8 @@ public class PfConceptContainer<C extends PfConcept, A extends PfNameVersion> ex
private static final Pattern KEY_ID_PATTERN = Pattern.compile(PfKey.KEY_ID_REGEXP);
@EmbeddedId
+ @VerifyKey
+ @NotNull
private PfConceptKey key;
@ManyToMany(cascade = CascadeType.ALL)
@@ -243,9 +247,7 @@ public class PfConceptContainer<C extends PfConcept, A extends PfNameVersion> ex
@Override
public BeanValidationResult validate(@NonNull String fieldName) {
- BeanValidationResult result = new BeanValidationResult(fieldName, this);
-
- result.addResult(validateKeyNotNull("key", key));
+ BeanValidationResult result = new PfValidator().validateTop(fieldName, this);
result.addResult(validateConceptMap());
return result;
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfConceptKey.java b/models-base/src/main/java/org/onap/policy/models/base/PfConceptKey.java
index 5e3295ec7..d200a693a 100644
--- a/models-base/src/main/java/org/onap/policy/models/base/PfConceptKey.java
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfConceptKey.java
@@ -26,6 +26,7 @@ import javax.persistence.Embeddable;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
+import org.onap.policy.common.parameters.annotations.Pattern;
import org.onap.policy.common.utils.validation.Assertions;
/**
@@ -43,9 +44,11 @@ public class PfConceptKey extends PfKeyImpl {
private static final long serialVersionUID = 8932717618579392561L;
@Column(name = NAME_TOKEN, length = 120)
+ @Pattern(regexp = NAME_REGEXP)
private String name;
@Column(name = VERSION_TOKEN, length = 20)
+ @Pattern(regexp = VERSION_REGEXP)
private String version;
/**
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfKeyImpl.java b/models-base/src/main/java/org/onap/policy/models/base/PfKeyImpl.java
index 3cbef75f9..bfeb870c1 100644
--- a/models-base/src/main/java/org/onap/policy/models/base/PfKeyImpl.java
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfKeyImpl.java
@@ -26,8 +26,6 @@ import java.util.List;
import lombok.Getter;
import lombok.NonNull;
import lombok.ToString;
-import org.onap.policy.common.parameters.BeanValidationResult;
-import org.onap.policy.common.parameters.ValidationResult;
import org.onap.policy.common.utils.validation.Assertions;
/**
@@ -242,16 +240,6 @@ public abstract class PfKeyImpl extends PfKey {
}
@Override
- public ValidationResult validate(@NonNull String fieldName) {
- BeanValidationResult result = new BeanValidationResult(fieldName, this);
-
- result.addResult(validateRegex(NAME_TOKEN, getName(), getNameRegEx()));
- result.addResult(validateRegex(VERSION_TOKEN, getVersion(), getVersionRegEx()));
-
- return result;
- }
-
- @Override
public void clean() {
setName(getName());
setVersion(getVersion());
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfKeyUse.java b/models-base/src/main/java/org/onap/policy/models/base/PfKeyUse.java
index 616284daf..b753bb14a 100644
--- a/models-base/src/main/java/org/onap/policy/models/base/PfKeyUse.java
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfKeyUse.java
@@ -23,11 +23,12 @@ package org.onap.policy.models.base;
import java.util.List;
import lombok.EqualsAndHashCode;
+import lombok.Getter;
import lombok.NonNull;
import lombok.ToString;
-import org.onap.policy.common.parameters.BeanValidationResult;
-import org.onap.policy.common.parameters.ValidationResult;
+import org.onap.policy.common.parameters.annotations.NotNull;
import org.onap.policy.common.utils.validation.Assertions;
+import org.onap.policy.models.base.validation.annotations.VerifyKey;
/**
* This class records a usage of a key in the system. When the list of keys being used by a concept
@@ -42,6 +43,9 @@ import org.onap.policy.common.utils.validation.Assertions;
public class PfKeyUse extends PfKey {
private static final long serialVersionUID = 2007147220109881705L;
+ @VerifyKey
+ @NotNull
+ @Getter
private PfKey usedKey;
/**
@@ -135,13 +139,6 @@ public class PfKeyUse extends PfKey {
}
@Override
- public ValidationResult validate(@NonNull String fieldName) {
- BeanValidationResult result = new BeanValidationResult(fieldName, this);
- result.addResult(validateKeyNotNull("usedKey", usedKey));
- return result;
- }
-
- @Override
public int compareTo(final PfConcept otherObj) {
Assertions.argumentNotNull(otherObj, "comparison object may not be null");
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 c87874774..82b8f93f6 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
@@ -35,7 +35,9 @@ import lombok.NonNull;
import org.onap.policy.common.parameters.BeanValidationResult;
import org.onap.policy.common.parameters.ObjectValidationResult;
import org.onap.policy.common.parameters.ValidationStatus;
+import org.onap.policy.common.parameters.annotations.NotNull;
import org.onap.policy.common.utils.validation.Assertions;
+import org.onap.policy.models.base.validation.annotations.VerifyKey;
/**
* This class is the base class for all models in the Policy Framework. All model classes inherit
@@ -63,6 +65,8 @@ public abstract class PfModel extends PfConcept {
private static final long serialVersionUID = -771659065637205430L;
@EmbeddedId
+ @VerifyKey
+ @NotNull
private PfConceptKey key;
/**
@@ -113,9 +117,7 @@ public abstract class PfModel extends PfConcept {
@Override
public BeanValidationResult validate(@NonNull String fieldName) {
- BeanValidationResult result = new BeanValidationResult(fieldName, this);
-
- result.addResult(validateKeyNotNull("key", key));
+ BeanValidationResult result = new PfValidator().validateTop(fieldName, this);
// Key consistency check
final Set<PfConceptKey> artifactKeySet = new TreeSet<>();
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfReferenceKey.java b/models-base/src/main/java/org/onap/policy/models/base/PfReferenceKey.java
index 83403ac43..9a986481b 100644
--- a/models-base/src/main/java/org/onap/policy/models/base/PfReferenceKey.java
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfReferenceKey.java
@@ -28,8 +28,8 @@ import javax.persistence.Embeddable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
-import org.onap.policy.common.parameters.BeanValidationResult;
-import org.onap.policy.common.parameters.ValidationResult;
+import org.onap.policy.common.parameters.annotations.NotNull;
+import org.onap.policy.common.parameters.annotations.Pattern;
import org.onap.policy.common.utils.validation.Assertions;
/**
@@ -73,15 +73,23 @@ public class PfReferenceKey extends PfKey {
private static final int LOCAL_NAME_FIELD = 3;
@Column(name = PARENT_KEY_NAME, length = 120)
+ @NotNull
+ @Pattern(regexp = NAME_REGEXP)
private String parentKeyName;
@Column(name = PARENT_KEY_VERSION, length = 15)
+ @NotNull
+ @Pattern(regexp = VERSION_REGEXP)
private String parentKeyVersion;
@Column(name = PARENT_LOCAL_NAME, length = 120)
+ @NotNull
+ @Pattern(regexp = LOCAL_NAME_REGEXP)
private String parentLocalName;
@Column(name = LOCAL_NAME, length = 120)
+ @NotNull
+ @Pattern(regexp = LOCAL_NAME_REGEXP)
private String localName;
/**
@@ -340,18 +348,6 @@ public class PfReferenceKey extends PfKey {
}
@Override
- public ValidationResult validate(@NonNull String fieldName) {
- BeanValidationResult result = new BeanValidationResult(fieldName, this);
-
- result.addResult(validateRegex(PARENT_KEY_NAME, parentKeyName, NAME_REGEXP));
- result.addResult(validateRegex(PARENT_KEY_VERSION, parentKeyVersion, VERSION_REGEXP));
- result.addResult(validateRegex(PARENT_LOCAL_NAME, parentLocalName, LOCAL_NAME_REGEXP));
- result.addResult(validateRegex(LOCAL_NAME, localName, LOCAL_NAME_REGEXP));
-
- return result;
- }
-
- @Override
public void clean() {
parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, parentKeyName, NAME_REGEXP);
parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION, parentKeyVersion, VERSION_REGEXP);
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfSearchableKey.java b/models-base/src/main/java/org/onap/policy/models/base/PfSearchableKey.java
index bed1a3598..3ff4160a3 100644
--- a/models-base/src/main/java/org/onap/policy/models/base/PfSearchableKey.java
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfSearchableKey.java
@@ -26,6 +26,7 @@ import javax.persistence.Embeddable;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
+import org.onap.policy.common.parameters.annotations.Pattern;
import org.onap.policy.common.utils.validation.Assertions;
/**
@@ -42,9 +43,11 @@ public class PfSearchableKey extends PfKeyImpl {
public static final String WILDCARD_NAME_REGEXP = "^[A-Za-z0-9\\-_\\.]+(?:\\.\\*)?$";
@Column(name = NAME_TOKEN, length = 120)
+ @Pattern(regexp = NAME_REGEXP)
private String name;
@Column(name = VERSION_TOKEN, length = 20)
+ @Pattern(regexp = VERSION_REGEXP)
private String version;
/**
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfTimestampKey.java b/models-base/src/main/java/org/onap/policy/models/base/PfTimestampKey.java
index 5be9b5f58..d12466c60 100644
--- a/models-base/src/main/java/org/onap/policy/models/base/PfTimestampKey.java
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfTimestampKey.java
@@ -29,6 +29,7 @@ import javax.persistence.Embeddable;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
+import org.onap.policy.common.parameters.annotations.Pattern;
import org.onap.policy.common.utils.validation.Assertions;
@Embeddable
@@ -40,9 +41,11 @@ public class PfTimestampKey extends PfKeyImpl {
private static final String TIMESTAMP_TOKEN = "timeStamp";
@Column(name = NAME_TOKEN, length = 120)
+ @Pattern(regexp = NAME_REGEXP)
private String name;
@Column(name = VERSION_TOKEN, length = 20)
+ @Pattern(regexp = VERSION_REGEXP)
private String version;
@Column(name = TIMESTAMP_TOKEN)
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
new file mode 100644
index 000000000..c4e46e0b5
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfValidator.java
@@ -0,0 +1,160 @@
+/*-
+ * ============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;
+
+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;
+
+public class PfValidator extends BeanValidator {
+
+ @Override
+ 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);
+ }
+
+ /**
+ * Verifies that the value is >= the minimum value.
+ *
+ * @param result where to add the validation result
+ * @param fieldName field whose value is being verified
+ * @param annot annotation against which the value is being verified
+ * @param value value to be verified
+ * @return {@code true} if the next check should be performed, {@code false} otherwise
+ */
+ public boolean verPfMin(BeanValidationResult result, String fieldName, PfMin annot, Object value) {
+ if (!(value instanceof Number)) {
+ return true;
+ }
+
+ Number num = (Number) value;
+ if (num.longValue() == annot.allowed()) {
+ // this value is always allowed
+ return true;
+ }
+
+ return verMin(result, fieldName, annot.value(), value);
+ }
+
+ /**
+ * 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}.
+ */
+ @Override
+ public boolean verCascade(BeanValidationResult result, String fieldName, Object value) {
+ if (value instanceof Validated) {
+ ValidationResult result2 = ((Validated) value).validate(fieldName);
+ result.addResult(result2);
+ return result2.isValid();
+ }
+
+ return super.verCascade(result, fieldName, value);
+ }
+
+ /**
+ * Validates a key.
+ *
+ * @param result where to add the validation result
+ * @param fieldName name of the field containing the key
+ * @param annot validation annotations for the key
+ * @param value value to be verified
+ * @return {@code true} if the next check should be performed, {@code false} otherwise
+ */
+ public boolean verKey(BeanValidationResult result, String fieldName, VerifyKey annot, Object value) {
+ if (!(value instanceof PfKey)) {
+ return true;
+ }
+
+ PfKey pfkey = (PfKey) value;
+ if (annot.keyNotNull() && pfkey.isNullKey()) {
+ result.addResult(new ObjectValidationResult(fieldName, xlate(pfkey), ValidationStatus.INVALID,
+ Validated.IS_A_NULL_KEY));
+ return false;
+ }
+
+ if (annot.valid()) {
+ verCascade(result, fieldName, value);
+ }
+
+ if (!(pfkey instanceof PfKeyImpl)) {
+ return true;
+ }
+
+ BeanValidationResult result2 = new BeanValidationResult(fieldName, value);
+
+ PfKeyImpl keyimpl = (PfKeyImpl) pfkey;
+
+ if (annot.nameNotNull() && keyimpl.isNullName()) {
+ result2.addResult(new ObjectValidationResult("name", pfkey.getName(), ValidationStatus.INVALID,
+ Validated.IS_NULL));
+ }
+
+ if (annot.versionNotNull() && keyimpl.isNullVersion()) {
+ result2.addResult(new ObjectValidationResult("version", pfkey.getVersion(), ValidationStatus.INVALID,
+ Validated.IS_NULL));
+ }
+
+ if (!result2.isClean()) {
+ result.addResult(result2);
+ }
+
+ return result2.isValid();
+ }
+
+ @Override
+ public Object xlate(Object value) {
+ return (value instanceof PfKey ? ((PfKey) value).getId() : value);
+ }
+}
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 b962d46ab..2c059ba4b 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
@@ -37,7 +37,7 @@ import org.onap.policy.common.parameters.ValidationStatus;
* Classes that can be validated. This can be used as a super class or as a stand-alone
* utility class.
*/
-public abstract class Validated {
+public class Validated {
public static final String IS_BLANK = "is blank";
public static final String IS_A_NULL_KEY = "is a null key";
public static final String IS_NULL = "is null";
@@ -48,12 +48,15 @@ public abstract class Validated {
public static final String VALUE_TOKEN = "value";
/**
- * Validates the fields of the object.
+ * Validates the fields of the object. The default method uses a {@link PfValidator}
+ * to validate the object.
*
* @param fieldName name of the field containing this
* @return the result, or {@code null}
*/
- public abstract ValidationResult validate(String fieldName);
+ public BeanValidationResult validate(@NonNull String fieldName) {
+ return new PfValidator().validateTop(fieldName, this);
+ }
/**
* Adds a result indicating that a value is invalid.
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
new file mode 100644
index 000000000..f3726003b
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/validation/annotations/PfEntries.java
@@ -0,0 +1,45 @@
+/*-
+ * ============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
new file mode 100644
index 000000000..363cf6f34
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/validation/annotations/PfItems.java
@@ -0,0 +1,82 @@
+/*-
+ * ============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
new file mode 100644
index 000000000..71f001848
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/validation/annotations/PfMin.java
@@ -0,0 +1,47 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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;
+
+/**
+ * Same as the "Min" annotation, but allows an extra value that is not in the range.
+ */
+@Retention(RUNTIME)
+@Target(FIELD)
+public @interface PfMin {
+
+ /**
+ * The minimum value allowed.
+ *
+ * @return the minimum value allowed
+ */
+ long value();
+
+ /**
+ * Allowed value.
+ */
+ long allowed();
+}
diff --git a/models-base/src/main/java/org/onap/policy/models/base/validation/annotations/VerifyKey.java b/models-base/src/main/java/org/onap/policy/models/base/validation/annotations/VerifyKey.java
new file mode 100644
index 000000000..cc8c882df
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/validation/annotations/VerifyKey.java
@@ -0,0 +1,57 @@
+/*-
+ * ============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;
+
+/**
+ * Validates a key.
+ */
+@Retention(RUNTIME)
+@Target(FIELD)
+public @interface VerifyKey {
+
+ /**
+ * Validates that key.isNullKey() is {@code false}.
+ */
+ boolean keyNotNull() default true;
+
+ /**
+ * Validates that key.isNullName() is {@code false}.
+ */
+ boolean nameNotNull() default true;
+
+ /**
+ * Validates that key.isNullVersion() is {@code false}.
+ */
+ boolean versionNotNull() default false;
+
+ /**
+ * Invokes key.validate(), avoiding the need to include the "Valid" annotation. Note:
+ * if this is {@code true}, then the "Valid" annotation should not be specified, as
+ * that would result in duplicate validation checks.
+ */
+ boolean valid() default true;
+}