/*- * ============LICENSE_START======================================================= * ONAP * ================================================================================ * 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. * 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.common.parameters; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.List; import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import org.onap.policy.common.parameters.annotations.NotNull; /** * Validator of a value. *

* Note: this currently does not support Min/Max validation of "short" or "byte"; these * annotations are simply ignored for these types. */ @NoArgsConstructor public class ValueValidator { /** * {@code True} if the value is allowed to be {@code null}, {@code false} otherwise. * Subclasses are expected to set this, typically based on the validation annotations * associated with the value. */ @Getter @Setter(AccessLevel.PROTECTED) private boolean nullAllowed = true; /** * Predicates to invoke to validate an object. *

* Note: each predicate is expected to return {@code true} if the next check is * allowed to proceed, {@code false} otherwise. In addition, if {@link #nullAllowed} * is {@code true}, then the predicates must be prepared to deal with a {@code null} * Object as their input parameter. */ protected List checkers = new ArrayList<>(10); /** * Determines if the validator has anything to check. * * @return {@code true} if the validator is empty (i.e., has nothing to check) */ public boolean isEmpty() { return checkers.isEmpty(); } /** * Performs validation of a single field. * * @param result validation results are added here * @param fieldName field whose value is being verified * @param value value to be validated */ protected void validateValue(BeanValidationResult result, String fieldName, Object value) { if (value == null && isNullAllowed()) { // value is null and null is allowed - just return return; } for (Checker checker : checkers) { if (!checker.test(result, fieldName, value)) { // invalid - don't bother with additional checks return; } } } /** * Looks for an annotation at the class or field level. If an annotation is found at * either the field or class level, then it adds a verifier to * {@link ValueValidator#checkers}. * * @param annotClass class of annotation to find * @param checker function to validate the value */ public void addAnnotation(Class annotClass, Checker checker) { var annot = getAnnotation(annotClass); if (annot != null) { checkers.add(checker); if (annotClass == NotNull.class) { setNullAllowed(false); } } } /** * Looks for an annotation at the class or field level. If an annotation is found at * either the field or class level, then it adds a verifier to * {@link ValueValidator#checkers}. * * @param annotClass class of annotation to find * @param checker function to validate the value */ public void addAnnotation(Class annotClass, CheckerWithAnnot checker) { var annot = getAnnotation(annotClass); if (annot != null) { checkers.add((result, fieldName, value) -> checker.test(result, fieldName, annot, value)); } } /** * Gets an annotation from the field or the class. The default method simply returns * {@code null}. * * @param annotClass annotation class of interest * @return the annotation, or {@code null} if neither the field nor the class has the * desired annotation */ public T getAnnotation(Class annotClass) { return null; } // functions to validate a value extracted from a field public static interface Checker { boolean test(BeanValidationResult result, String fieldName, Object value); } public static interface CheckerWithAnnot { boolean test(BeanValidationResult result, String fieldName, T annotation, Object value); } }