/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2023 Nordix Foundation.
+ * Copyright (C) 2023-2026 OpenInfra Foundation Europe. 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.
package org.onap.policy.clamp.models.acm.concepts;
+import jakarta.validation.constraints.NotNull;
import java.util.UUID;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
-import org.onap.policy.common.parameters.annotations.NotNull;
@NoArgsConstructor
@Data
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2022,2025 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2022-2026 OpenInfra Foundation Europe. 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.
package org.onap.policy.clamp.models.acm.document.base;
+import jakarta.validation.constraints.Pattern;
import java.io.Serial;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.ToString;
-import org.onap.policy.common.parameters.annotations.Pattern;
import org.onap.policy.common.utils.validation.Assertions;
import org.onap.policy.models.base.PfConceptKey;
import org.onap.policy.models.base.PfKeyImpl;
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2022,2024-2025 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2022-2026 OpenInfra Foundation Europe. 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.
package org.onap.policy.clamp.models.acm.document.concepts;
+import jakarta.validation.constraints.NotNull;
import java.io.Serial;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
-import org.onap.policy.common.parameters.annotations.NotNull;
import org.onap.policy.models.base.PfUtils;
import org.onap.policy.models.tosca.authorative.concepts.ToscaCapabilityAssignment;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
-import lombok.NonNull;
-import org.onap.policy.common.parameters.BeanValidationResult;
+import org.onap.policy.models.base.PfConceptKey;
+import org.onap.policy.models.base.validation.annotations.VerifyKey;
import org.onap.policy.models.tosca.authorative.concepts.ToscaCapabilityType;
@Data
}
@Override
- public BeanValidationResult validate(@NonNull String fieldName) {
- var result = super.validate(fieldName);
-
- validateKeyVersionNotNull(result, "key", getConceptKey());
-
- return result;
+ @VerifyKey(keyNotNull = false, nameNotNull = false, versionNotNull = true)
+ public PfConceptKey getConceptKey() {
+ return super.getConceptKey();
}
}
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2022,2025 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2022-2026 OpenInfra Foundation Europe. 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.
package org.onap.policy.clamp.models.acm.document.concepts;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
import java.io.Serial;
import java.util.List;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
-import org.onap.policy.common.parameters.annotations.NotNull;
-import org.onap.policy.common.parameters.annotations.Valid;
import org.onap.policy.models.base.PfUtils;
import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType;
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2022,2024 Nordix Foundation.
+ * Copyright (C) 2022-2026 OpenInfra Foundation Europe. 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.
package org.onap.policy.clamp.models.acm.document.concepts;
import com.google.gson.annotations.SerializedName;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
import java.io.Serial;
import java.io.Serializable;
import java.util.LinkedHashMap;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.onap.policy.clamp.models.acm.document.base.DocConceptKey;
-import org.onap.policy.common.parameters.annotations.NotBlank;
-import org.onap.policy.common.parameters.annotations.NotNull;
import org.onap.policy.models.base.PfAuthorative;
import org.onap.policy.models.base.PfConceptKey;
import org.onap.policy.models.base.PfKey;
private String derivedFrom;
@SuppressWarnings("squid:S1948")
- private Map<@NotNull @NotBlank String, @NotNull @NotBlank Object> metadata = new LinkedHashMap<>();
+ private Map<@NotBlank String, @NotNull Object> metadata = new LinkedHashMap<>();
- @NotBlank
private String description;
private transient T toscaEntity;
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2022,2025 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2022-2026 OpenInfra Foundation Europe. 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.
package org.onap.policy.clamp.models.acm.document.concepts;
+import jakarta.validation.Valid;
import java.io.Serial;
import java.util.List;
import java.util.Map;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.onap.policy.clamp.models.acm.document.base.DocUtil;
-import org.onap.policy.common.parameters.annotations.Valid;
import org.onap.policy.models.base.PfUtils;
import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2022,2025 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2022-2026 OpenInfra Foundation Europe. 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.
package org.onap.policy.clamp.models.acm.document.concepts;
+import jakarta.validation.Valid;
import java.io.Serial;
import java.util.List;
import java.util.Map;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.onap.policy.clamp.models.acm.document.base.DocUtil;
-import org.onap.policy.common.parameters.annotations.Valid;
import org.onap.policy.models.base.PfUtils;
import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeType;
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2022,2024 Nordix Foundation.
+ * Copyright (C) 2022-2026 OpenInfra Foundation Europe. 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.
package org.onap.policy.clamp.models.acm.document.concepts;
import com.google.gson.annotations.SerializedName;
+import jakarta.validation.constraints.NotNull;
import java.io.Serial;
import java.io.Serializable;
import lombok.Data;
import lombok.NoArgsConstructor;
-import org.onap.policy.common.parameters.annotations.NotNull;
import org.onap.policy.models.base.PfAuthorative;
import org.onap.policy.models.base.PfKey;
import org.onap.policy.models.base.PfUtils;
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2022 Nordix Foundation.
+ * Copyright (C) 2022-2026 OpenInfra Foundation Europe. 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.
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.ToString;
-import org.onap.policy.common.parameters.BeanValidationResult;
+import org.onap.policy.models.base.PfConceptKey;
+import org.onap.policy.models.base.validation.annotations.VerifyKey;
import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
@Data
}
@Override
- public BeanValidationResult validate(String fieldName) {
- var result = super.validate(fieldName);
-
- validateKeyVersionNotNull(result, "key", getConceptKey());
-
- return result;
+ @VerifyKey(keyNotNull = false, nameNotNull = false, versionNotNull = true)
+ public PfConceptKey getConceptKey() {
+ return super.getConceptKey();
}
}
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2022,2024 Nordix Foundation.
+ * Copyright (C) 2022-2026 OpenInfra Foundation Europe. 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.
package org.onap.policy.clamp.models.acm.document.concepts;
import com.google.gson.annotations.SerializedName;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
import java.io.Serial;
import java.io.Serializable;
import java.util.LinkedHashMap;
import org.apache.commons.lang3.ObjectUtils;
import org.onap.policy.clamp.models.acm.document.base.DocConceptKey;
import org.onap.policy.clamp.models.acm.document.base.DocUtil;
-import org.onap.policy.common.parameters.annotations.NotBlank;
-import org.onap.policy.common.parameters.annotations.NotNull;
-import org.onap.policy.common.parameters.annotations.Valid;
import org.onap.policy.models.base.PfAuthorative;
import org.onap.policy.models.base.PfUtils;
import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
@NotNull
private String typeVersion;
- @NotBlank
private String description;
@SerializedName("default")
- @NotBlank
@SuppressWarnings("squid:S1948")
private Object defaultValue;
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2022,2025 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2022-2026 OpenInfra Foundation Europe. 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.
package org.onap.policy.clamp.models.acm.document.concepts;
import com.google.gson.annotations.SerializedName;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
import java.io.Serial;
import java.util.LinkedHashMap;
import java.util.Map;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.ObjectUtils;
import org.onap.policy.clamp.models.acm.document.base.DocUtil;
-import org.onap.policy.common.parameters.annotations.NotBlank;
-import org.onap.policy.common.parameters.annotations.NotNull;
-import org.onap.policy.common.parameters.annotations.Valid;
import org.onap.policy.models.base.PfKey;
import org.onap.policy.models.base.PfUtils;
import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
public static final String DEFAULT_VERSION = "1.0.0";
@SerializedName("tosca_definitions_version")
- @NotNull
@NotBlank
private String toscaDefinitionsVersion;
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2022 Nordix Foundation.
+ * Copyright (C) 2022-2026 OpenInfra Foundation Europe. 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.
package org.onap.policy.clamp.models.acm.document.concepts;
import com.google.gson.annotations.SerializedName;
+import jakarta.validation.Valid;
import java.io.Serial;
import java.io.Serializable;
import java.util.LinkedHashMap;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.onap.policy.clamp.models.acm.document.base.DocUtil;
-import org.onap.policy.common.parameters.annotations.Valid;
import org.onap.policy.models.base.PfAuthorative;
import org.onap.policy.models.base.PfUtils;
import org.onap.policy.models.base.Validated;
package org.onap.policy.clamp.models.acm.document.concepts;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
import java.io.Serial;
import java.util.Collection;
import java.util.LinkedHashMap;
import org.apache.commons.collections4.CollectionUtils;
import org.onap.policy.clamp.models.acm.document.base.DocConceptKey;
import org.onap.policy.clamp.models.acm.document.base.DocUtil;
-import org.onap.policy.common.parameters.annotations.NotBlank;
-import org.onap.policy.common.parameters.annotations.NotNull;
-import org.onap.policy.common.parameters.annotations.Valid;
import org.onap.policy.models.base.PfUtils;
import org.onap.policy.models.tosca.authorative.concepts.ToscaWithToscaProperties;
import org.onap.policy.models.tosca.utils.ToscaUtils;
private static final long serialVersionUID = 1L;
@SuppressWarnings("squid:S1948")
- private Map<@NotNull @NotBlank String, @NotNull @Valid DocToscaProperty> properties;
+ private Map<@NotBlank String, @NotNull @Valid DocToscaProperty> properties;
/**
* Copy constructor.
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2021-2025 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2021-2026 OpenInfra Foundation Europe. 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.
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
import org.onap.policy.clamp.models.acm.concepts.SubState;
import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
-import org.onap.policy.common.parameters.annotations.NotNull;
-import org.onap.policy.common.parameters.annotations.Valid;
import org.onap.policy.models.base.PfAuthorative;
import org.onap.policy.models.base.PfUtils;
import org.onap.policy.models.base.Validated;
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2022-2025 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2022-2026 OpenInfra Foundation Europe. 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.
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Pattern;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Set;
import org.onap.policy.clamp.models.acm.concepts.StateChangeResult;
import org.onap.policy.clamp.models.acm.document.concepts.DocToscaServiceTemplate;
import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
-import org.onap.policy.common.parameters.annotations.NotNull;
-import org.onap.policy.common.parameters.annotations.Pattern;
-import org.onap.policy.common.parameters.annotations.Valid;
import org.onap.policy.models.base.PfAuthorative;
import org.onap.policy.models.base.PfKey;
import org.onap.policy.models.base.Validated;
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2021-2025 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2021-2026 OpenInfra Foundation Europe. All rights reserved.
* ================================================================================
* Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
* ================================================================================
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.Table;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
import java.util.Map;
import java.util.UUID;
import java.util.function.UnaryOperator;
import org.onap.policy.clamp.models.acm.concepts.LockState;
import org.onap.policy.clamp.models.acm.concepts.MigrationState;
import org.onap.policy.clamp.models.acm.concepts.SubState;
-import org.onap.policy.common.parameters.annotations.NotNull;
-import org.onap.policy.common.parameters.annotations.Valid;
import org.onap.policy.models.base.PfAuthorative;
import org.onap.policy.models.base.PfConceptKey;
import org.onap.policy.models.base.PfUtils;
@NotNull
private String instanceId;
+ @Valid
@VerifyKey
@NotNull
@AttributeOverride(name = "name", column = @Column(name = "definition_name"))
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.Table;
+import jakarta.validation.constraints.NotNull;
import java.sql.Timestamp;
import java.util.UUID;
import lombok.Data;
import lombok.NonNull;
import org.onap.policy.clamp.models.acm.document.concepts.DocMessage;
import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
-import org.onap.policy.common.parameters.annotations.NotNull;
import org.onap.policy.models.base.PfAuthorative;
import org.onap.policy.models.base.Validated;
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.Table;
+import jakarta.validation.constraints.NotNull;
import java.sql.Timestamp;
import java.util.UUID;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
-import org.onap.policy.common.parameters.annotations.NotNull;
import org.onap.policy.models.base.Validated;
@Entity
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2023,2025 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2023-2026 OpenInfra Foundation Europe. 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.
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.Table;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
import java.util.Map;
import java.util.UUID;
import java.util.function.UnaryOperator;
import lombok.EqualsAndHashCode;
import org.onap.policy.clamp.models.acm.concepts.AcTypeState;
import org.onap.policy.clamp.models.acm.concepts.NodeTemplateState;
-import org.onap.policy.common.parameters.annotations.NotNull;
-import org.onap.policy.common.parameters.annotations.Valid;
import org.onap.policy.models.base.PfAuthorative;
import org.onap.policy.models.base.PfConceptKey;
import org.onap.policy.models.base.PfUtils;
@Column
private String participantId;
+ @Valid
@VerifyKey
@NotNull
@AttributeOverride(name = "name", column = @Column(name = "nodeTemplate_name"))
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2021-2025 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2021-2026 OpenInfra Foundation Europe. 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.
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import lombok.NonNull;
import org.apache.commons.lang3.ObjectUtils;
import org.onap.policy.clamp.models.acm.concepts.Participant;
-import org.onap.policy.common.parameters.annotations.NotNull;
-import org.onap.policy.common.parameters.annotations.Valid;
import org.onap.policy.models.base.PfAuthorative;
import org.onap.policy.models.base.Validated;
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2024 Nordix Foundation.
+ * Copyright (C) 2024-2026 OpenInfra Foundation Europe. 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.
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.Table;
+import jakarta.validation.constraints.NotNull;
import java.sql.Timestamp;
import java.util.UUID;
import lombok.Data;
import org.onap.policy.clamp.models.acm.concepts.ParticipantReplica;
import org.onap.policy.clamp.models.acm.concepts.ParticipantState;
import org.onap.policy.clamp.models.acm.utils.TimestampHelper;
-import org.onap.policy.common.parameters.annotations.NotNull;
import org.onap.policy.models.base.PfAuthorative;
import org.onap.policy.models.base.Validated;
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2023 Nordix Foundation.
+ * Copyright (C) 2023-2026 OpenInfra Foundation Europe. 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.
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.Table;
+import jakarta.validation.constraints.NotNull;
import java.util.UUID;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import org.apache.commons.lang3.ObjectUtils;
import org.onap.policy.clamp.models.acm.concepts.ParticipantSupportedElementType;
-import org.onap.policy.common.parameters.annotations.NotNull;
import org.onap.policy.models.base.PfAuthorative;
import org.onap.policy.models.base.Validated;
@Column
@Id
private String id;
+
@NotNull
@Column
private String participantId;
<?xml version="1.0" encoding="UTF-8"?>
<!--
============LICENSE_START=======================================================
- Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+ Copyright (C) 2025-2026 OpenInfra Foundation Europe. 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.
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-validation</artifactId>
+ </dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
/*-
* ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
* Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2024 Nordix Foundation
+ * Modifications Copyright (C) 2024-2026 OpenInfra Foundation Europe. 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.
* 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
* ============LICENSE_END=========================================================
*/
package org.onap.policy.common.parameters;
-import java.lang.reflect.Field;
-import java.util.Collection;
-import java.util.Map;
-import java.util.Map.Entry;
-import org.apache.commons.lang3.StringUtils;
-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.Pattern;
-import org.onap.policy.common.parameters.annotations.Valid;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import jakarta.validation.Validation;
+import jakarta.validation.Validator;
+import jakarta.validation.ValidatorFactory;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
-/**
- * Bean validator, supporting the parameter annotations.
- */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class BeanValidator {
- public static final Logger logger = LoggerFactory.getLogger(BeanValidator.class);
+ private static final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
+ private static final Validator validator = factory.getValidator();
/**
- * Validates top level fields within an object. For each annotated field, it retrieves
- * the value using the public "getter" method for the field. If there is no public
- * "getter" method, then it throws an exception. Otherwise, it validates the retrieved
- * value based on the annotations. This recurses through super classes looking for
- * fields to be verified, but it does not examine any interfaces.
+ * Validates the given bean.
*
- * @param name name of the object being validated
- * @param object object to be validated. If {@code null}, then an empty result is
- * returned
+ * @param <T> the type of the bean
+ * @param bean the bean to validate
+ * @param beanDescription description of the bean
* @return the validation result
*/
- public BeanValidationResult validateTop(String name, Object object) {
- var result = new BeanValidationResult(name, object);
- if (object == null) {
- return result;
+ public static <T> BeanValidationResult validate(final String beanDescription, final T bean) {
+ final var result = new BeanValidationResult(beanDescription, bean);
+ final var violations = validator.validate(bean);
+ for (final var violation : violations) {
+ result.addResult(
+ violation.getPropertyPath().toString(),
+ violation.getInvalidValue(),
+ ValidationStatus.INVALID,
+ violation.getMessage());
}
-
- // check class hierarchy - don't need to check interfaces
- for (Class<?> clazz = object.getClass(); clazz != null; clazz = clazz.getSuperclass()) {
- validateFields(result, object, clazz);
- }
-
return result;
}
-
- /**
- * Adds validators based on the annotations that are available.
- *
- * @param validator where to add the validators
- */
- protected void addValidators(ValueValidator validator) {
- validator.addAnnotation(NotNull.class, this::verNotNull);
- validator.addAnnotation(NotBlank.class, this::verNotBlank);
- validator.addAnnotation(Min.class, this::verMin);
- validator.addAnnotation(Pattern.class, this::verRegex);
- validator.addAnnotation(Valid.class, this::verCascade);
- }
-
- /**
- * Performs validation of all annotated fields found within the class.
- *
- * @param result validation results are added here
- * @param object object whose fields are to be validated
- * @param clazz class, within the object's hierarchy, to be examined for fields to be
- * verified
- */
- private void validateFields(BeanValidationResult result, Object object, Class<?> clazz) {
- for (Field field : clazz.getDeclaredFields()) {
- var validator = makeFieldValidator(clazz, field);
- validator.validateField(result, object);
- }
- }
-
- /**
- * Verifies that the value is not null.
- *
- * @param result where to add the validation result
- * @param fieldName field whose 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 verNotNull(BeanValidationResult result, String fieldName, Object value) {
- if (value == null) {
- result.addResult(fieldName, xlate(value), ValidationStatus.INVALID, "is null");
- return false;
- }
-
- return true;
- }
-
- /**
- * Verifies that the value is not blank. Note: this does <i>not</i> verify that the
- * value is not {@code null}.
- *
- * @param result where to add the validation result
- * @param fieldName field whose 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 verNotBlank(BeanValidationResult result, String fieldName, Object value) {
- if (value instanceof String && StringUtils.isBlank(value.toString())) {
- result.addResult(fieldName, xlate(value), ValidationStatus.INVALID, "is blank");
- return false;
- }
-
- return true;
- }
-
- /**
- * Verifies that the value matches a regular expression.
- *
- * @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 verRegex(BeanValidationResult result, String fieldName, Pattern annot, Object value) {
- try {
- if (value instanceof String && com.google.re2j.Pattern.matches(annot.regexp(), value.toString())) {
- return true;
- }
-
- } catch (RuntimeException e) {
- logger.warn("validation error for regular expression: {}", annot.regexp(), e);
- }
-
- result.addResult(fieldName, xlate(value), ValidationStatus.INVALID,
- "does not match regular expression " + annot.regexp());
- return false;
- }
-
- /**
- * 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 verMin(BeanValidationResult result, String fieldName, Min annot, Object value) {
- return verMin(result, fieldName, annot.value(), value);
- }
-
- /**
- * 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 min minimum 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 verMin(BeanValidationResult result, String fieldName, long min, Object value) {
- if (!(value instanceof Number)) {
- return true;
- }
-
- Number num = (Number) value;
- if (num instanceof Integer || num instanceof Long) {
- if (num.longValue() >= min) {
- return true;
- }
-
- } else if (num instanceof Float || num instanceof Double) {
- if (num.doubleValue() >= min) {
- return true;
- }
-
- } else {
- return true;
- }
-
- result.addResult(fieldName, xlate(value), ValidationStatus.INVALID,
- "is below the minimum value: " + min);
- return false;
- }
-
- /**
- * Verifies that the value is valid by recursively invoking
- * {@link #validateTop(String, Object)}.
- *
- * @param result where to add the validation result
- * @param fieldName field whose 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 verCascade(BeanValidationResult result, String fieldName, Object value) {
- if (value == null || value instanceof Collection || value instanceof Map) {
- return true;
- }
-
- BeanValidationResult result2 = (value instanceof ParameterGroup parameterGroup ? parameterGroup.validate()
- : validateTop(fieldName, value));
-
- if (result2.isClean()) {
- return true;
- }
-
- result.addResult(result2);
-
- return result2.isValid();
- }
-
- /**
- * Validates the items in a collection.
- *
- * @param result where to add the validation result
- * @param fieldName name of the field containing the collection
- * @param itemValidator validator for individual items within the list
- * @param value value to be verified
- * @return {@code true} if the next check should be performed, {@code false} otherwise
- */
- public boolean verCollection(BeanValidationResult result, String fieldName, ValueValidator itemValidator,
- Object value) {
-
- if (!(value instanceof Collection)) {
- return true;
- }
-
- Collection<?> list = (Collection<?>) value;
-
- var result2 = new BeanValidationResult(fieldName, value);
- var count = 0;
- for (Object item : list) {
- itemValidator.validateValue(result2, String.valueOf(count++), item);
- }
-
- if (result2.isClean()) {
- return true;
- }
-
- result.addResult(result2);
- return false;
- }
-
- /**
- * Validates the items in a Map.
- *
- * @param result where to add the validation result
- * @param fieldName name of the field containing the map
- * @param keyValidator validator for an individual key within the Map entry
- * @param valueValidator validator for an individual value within the Map entry
- * @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, ValueValidator keyValidator,
- ValueValidator valueValidator, Object value) {
-
- if (!(value instanceof Map)) {
- return true;
- }
-
- Map<?, ?> map = (Map<?, ?>) value;
-
- var result2 = new BeanValidationResult(fieldName, value);
-
- for (Entry<?, ?> entry : map.entrySet()) {
- String name = getEntryName(entry);
-
- var result3 = new BeanValidationResult(name, entry);
- keyValidator.validateValue(result3, "key", entry.getKey());
- valueValidator.validateValue(result3, "value", entry.getValue());
-
- if (!result3.isClean()) {
- result2.addResult(result3);
- }
- }
-
- if (result2.isClean()) {
- return true;
- }
-
- result.addResult(result2);
- return false;
- }
-
- /**
- * Gets a name for an entry.
- *
- * @param entry entry whose name is to be determined
- * @return a name for the entry
- */
- protected <K, V> String getEntryName(Map.Entry<K, V> entry) {
- var key = entry.getKey();
- if (key == null) {
- return "";
- }
-
- return key.toString();
- }
-
- /**
- * Makes a field validator.
- *
- * @param clazz class containing the field
- * @param field field of interest
- * @return a validator for the given field
- */
- protected FieldValidator makeFieldValidator(Class<?> clazz, Field field) {
- return new FieldValidator(this, clazz, field);
- }
-
- /**
- * Translates a value to something printable, for use by
- * {@link ObjectValidationResult}. This default method simply returns the original
- * value.
- *
- * @param value value to be translated
- * @return the translated value
- */
- public Object xlate(Object value) {
- return value;
- }
}
+++ /dev/null
-/*-
- * ============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 com.google.gson.annotations.SerializedName;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AnnotatedParameterizedType;
-import java.lang.reflect.AnnotatedType;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.Collection;
-import java.util.Map;
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.Setter;
-import org.apache.commons.lang3.StringUtils;
-import org.onap.policy.common.parameters.annotations.NotNull;
-
-/**
- * Validator of the contents of a field, supporting the parameter annotations.
- */
-public class FieldValidator extends ValueValidator {
-
- /**
- * {@code True} if there is a field-level annotation, {@code false} otherwise.
- */
- @Getter
- @Setter(AccessLevel.PROTECTED)
- private boolean fieldAnnotated = false;
-
- /**
- * Class containing the field of interest.
- */
- private final Class<?> clazz;
-
- /**
- * Field of interest.
- */
- private final Field field;
-
- /**
- * Name of the field when serialized (i.e., as the client would know it).
- */
- private final String serializedName;
-
- /**
- * Method to retrieve the field's value.
- */
- private Method accessor;
-
-
- /**
- * Constructs the object.
- *
- * @param validator provider of validation methods
- * @param clazz class containing the field
- * @param field field whose value is to be validated
- */
- public FieldValidator(BeanValidator validator, Class<?> clazz, Field field) {
- this.clazz = clazz;
- this.field = field;
-
- String fieldName = field.getName();
- if (fieldName.contains("$")) {
- serializedName = fieldName;
- return;
- }
-
- SerializedName serAnnot = field.getAnnotation(SerializedName.class);
- serializedName = (serAnnot != null ? serAnnot.value() : fieldName);
-
- validator.addValidators(this);
- addListValidator(validator);
- addMapValidator(validator);
-
- if (checkers.isEmpty()) {
- // has no annotations - nothing to check
- return;
- }
-
- // verify the field type is of interest
- int mod = field.getModifiers();
- if (Modifier.isStatic(mod)) {
- classOnly(clazz.getName() + "." + fieldName + " is annotated but the field is static");
- checkers.clear();
- return;
- }
-
- // get the field's "getter" method
- accessor = getAccessor(clazz, fieldName);
- if (accessor == null) {
- classOnly(clazz.getName() + "." + fieldName + " is annotated but has no \"get\" method");
- checkers.clear();
- return;
- }
-
- // determine if null is allowed
- if (field.getAnnotation(NotNull.class) != null || clazz.getAnnotation(NotNull.class) != null) {
- setNullAllowed(false);
- }
- }
-
- /**
- * Adds validators for the individual items within a collection, if the field is a
- * collection.
- *
- * @param validator provider of validation methods
- */
- private void addListValidator(BeanValidator validator) {
- if (!Collection.class.isAssignableFrom(field.getType())) {
- return;
- }
-
- var tannot = field.getAnnotatedType();
- if (!(tannot instanceof AnnotatedParameterizedType)) {
- return;
- }
-
- AnnotatedType[] targs = ((AnnotatedParameterizedType) tannot).getAnnotatedActualTypeArguments();
- if (targs.length != 1) {
- return;
- }
-
- var itemValidator = new ItemValidator(validator, targs[0]);
- if (itemValidator.isEmpty()) {
- return;
- }
-
- checkers.add((result, fieldName, value) -> validator.verCollection(result, fieldName, itemValidator, value));
- }
-
- /**
- * Adds validators for the individual entries within a map, if the field is a map.
- *
- * @param validator provider of validation methods
- */
- private void addMapValidator(BeanValidator validator) {
- if (!Map.class.isAssignableFrom(field.getType())) {
- return;
- }
-
- var tannot = field.getAnnotatedType();
- if (!(tannot instanceof AnnotatedParameterizedType)) {
- return;
- }
-
- AnnotatedType[] targs = ((AnnotatedParameterizedType) tannot).getAnnotatedActualTypeArguments();
- if (targs.length != 2) {
- return;
- }
-
- var keyValidator = new ItemValidator(validator, targs[0]);
- var valueValidator = new ItemValidator(validator, targs[1]);
- if (keyValidator.isEmpty() && valueValidator.isEmpty()) {
- return;
- }
-
- checkers.add((result, fieldName, value) -> validator.verMap(result, fieldName, keyValidator, valueValidator,
- value));
- }
-
- /**
- * Performs validation of a single field.
- *
- * @param result validation results are added here
- * @param object object whose field is to be validated
- */
- public void validateField(BeanValidationResult result, Object object) {
- if (isEmpty()) {
- // has no annotations - nothing to check
- return;
- }
-
- // get the value
- Object value = getValue(object, accessor);
-
- validateValue(result, serializedName, value);
- }
-
- /**
- * Gets the value from the object using the accessor function.
- *
- * @param object object whose value is to be retrieved
- * @param accessor "getter" method
- * @return the object's value
- */
- private Object getValue(Object object, Method accessor) {
- try {
- return accessor.invoke(object);
-
- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
- throw new IllegalArgumentException(clazz.getName() + "." + field.getName() + " accessor threw an exception",
- e);
- }
- }
-
- /**
- * Throws an exception if there are field-level annotations.
- *
- * @param exceptionMessage exception message
- */
- private void classOnly(String exceptionMessage) {
- if (isFieldAnnotated()) {
- throw new IllegalArgumentException(exceptionMessage);
- }
- }
-
- /**
- * Gets an annotation from the field or the class.
- *
- * @param annotClass annotation class of interest
- * @return the annotation, or {@code null} if neither the field nor the class has the
- * desired annotation
- */
- @Override
- public <T extends Annotation> T getAnnotation(Class<T> annotClass) {
-
- // field annotation takes precedence over class annotation
- var annot = field.getAnnotation(annotClass);
- if (annot != null) {
- setFieldAnnotated(true);
- return annot;
- }
-
- return clazz.getAnnotation(annotClass);
- }
-
- /**
- * Gets an accessor method for the given field.
- *
- * @param clazz class whose methods are to be searched
- * @param fieldName field whose "getter" is to be identified
- * @return the field's "getter" method, or {@code null} if it is not found
- */
- private Method getAccessor(Class<?> clazz, String fieldName) {
- var capname = StringUtils.capitalize(fieldName);
- var accessor2 = getMethod(clazz, "get" + capname);
- if (accessor2 != null) {
- return accessor2;
- }
-
- return getMethod(clazz, "is" + capname);
- }
-
- /**
- * Gets the "getter" method having the specified name.
- *
- * @param clazz class whose methods are to be searched
- * @param methodName name of the method of interest
- * @return the method, or {@code null} if it is not found
- */
- private Method getMethod(Class<?> clazz, String methodName) {
- for (Method method : clazz.getMethods()) {
- if (methodName.equals(method.getName()) && validMethod(method)) {
- return method;
- }
- }
-
- return null;
- }
-
- /**
- * Determines if a method is a valid "getter".
- *
- * @param method method to be checked
- * @return {@code true} if the method is a valid "getter", {@code false} otherwise
- */
- private boolean validMethod(Method method) {
- int mod = method.getModifiers();
- return !(Modifier.isStatic(mod) || method.getReturnType() == void.class || method.getParameterCount() != 0);
- }
-}
+++ /dev/null
-/*-
- * ============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.common.parameters;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AnnotatedType;
-
-/**
- * Validator of an "item", which is typically found in a collection, or the key or value
- * components of an entry in a Map.
- */
-public class ItemValidator extends ValueValidator {
- private final AnnotatedType annotatedType;
-
- /**
- * Constructs the object.
- *
- * @param validator provider of validation methods
- * @param annotatedType a type having validation annotations to be
- * applied to the item
- */
- public ItemValidator(BeanValidator validator, AnnotatedType annotatedType) {
- this(validator, annotatedType, true);
- }
-
- /**
- * Constructs the object.
- *
- * @param validator provider of validation methods
- * @param annotatedType a type having validation annotations to be
- * applied to the item
- * @param addValidators {@code true} if to add validators
- */
- public ItemValidator(BeanValidator validator, AnnotatedType annotatedType, boolean addValidators) {
- this.annotatedType = annotatedType;
-
- if (addValidators) {
- validator.addValidators(this);
- }
- }
-
- /**
- * Gets an annotation from the field or the class.
- *
- * @param annotClass annotation class of interest
- * @return the annotation, or {@code null} if the {@link #annotatedType} does
- * not contain the desired annotation
- */
- @Override
- public <T extends Annotation> T getAnnotation(Class<T> annotClass) {
- return annotatedType.getAnnotation(annotClass);
- }
-}
* ONAP
* ================================================================================
* Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2026 OpenInfra Foundation Europe. 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.
package org.onap.policy.common.parameters;
+import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
-import org.onap.policy.common.parameters.annotations.NotBlank;
-import org.onap.policy.common.parameters.annotations.NotNull;
/**
* Implementation of a parameter group.
*/
-@NotNull
-@NotBlank
@Getter
@Setter
@NoArgsConstructor
/**
* Group name.
*/
+ @NotBlank
private String name;
@Override
public BeanValidationResult validate() {
- return new BeanValidator().validateTop(getClass().getSimpleName(), this);
+ return BeanValidator.validate(getClass().getSimpleName(), this);
}
}
+++ /dev/null
-/*-
- * ============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.
- * <p/>
- * 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.
- * <p/>
- * 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<Checker> 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 <T extends Annotation> void addAnnotation(Class<T> 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 <T extends Annotation> void addAnnotation(Class<T> annotClass, CheckerWithAnnot<T> 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 extends Annotation> T getAnnotation(Class<T> 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<T extends Annotation> {
- boolean test(BeanValidationResult result, String fieldName, T annotation, Object value);
- }
-}
+++ /dev/null
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * 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.
- * 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.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;
-import java.lang.annotation.Target;
-
-@Retention(RUNTIME)
-@Target({FIELD, TYPE_USE})
-public @interface Min {
-
- /**
- * The minimum value allowed.
- *
- * @return the minimum value allowed
- */
- long value();
-}
+++ /dev/null
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * 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.
- * 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.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.ElementType.TYPE_USE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Indicates that a field (i.e., String) may not be empty.
- */
-@Retention(RUNTIME)
-@Target({TYPE, FIELD, TYPE_USE})
-public @interface NotBlank {
-
-}
+++ /dev/null
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * 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.
- * 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.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.ElementType.TYPE_USE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-/**
- * Indicates that a field may not be null.
- */
-@Retention(RUNTIME)
-@Target({TYPE, FIELD, TYPE_USE})
-public @interface NotNull {
-
-}
+++ /dev/null
-/*-
- * ============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.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;
-import java.lang.annotation.Target;
-
-@Retention(RUNTIME)
-@Target({FIELD, TYPE_USE})
-public @interface Pattern {
-
- /**
- * Regular expression to be matched.
- */
- String regexp();
-}
+++ /dev/null
-/*-
- * ============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.annotations;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.ElementType.TYPE_USE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-@Retention(RUNTIME)
-@Target({TYPE, FIELD, TYPE_USE})
-public @interface Valid {
-
-}
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2019, 2024 Nordix Foundation.
+ * Copyright (C) 2019-2026 OpenInfra Foundation Europe. 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");
package org.onap.policy.common.parameters.topic;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
import java.util.List;
import lombok.Getter;
import lombok.Setter;
import org.onap.policy.common.parameters.BeanValidationResult;
import org.onap.policy.common.parameters.ParameterGroupImpl;
import org.onap.policy.common.parameters.ValidationStatus;
-import org.onap.policy.common.parameters.annotations.NotBlank;
-import org.onap.policy.common.parameters.annotations.NotNull;
/**
* Class to hold all parameters needed for topic properties.
*
* @author Ajith Sreekumar (ajith.sreekumar@est.tech)
*/
-@NotNull
-@NotBlank
@Getter
@Setter
public class TopicParameterGroup extends ParameterGroupImpl {
- private List<TopicParameters> topicSources;
- private List<TopicParameters> topicSinks;
+ @NotNull
+ private List<@Valid TopicParameters> topicSources;
+ @NotNull
+ private List<@Valid TopicParameters> topicSinks;
public TopicParameterGroup() {
super(TopicParameterGroup.class.getSimpleName());
/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2019, 2024 Nordix Foundation.
+ * Copyright (C) 2019-2026 OpenInfra Foundation Europe. All rights reserved.
* Modifications Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
package org.onap.policy.common.parameters.topic;
+import jakarta.validation.constraints.NotBlank;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
-import org.onap.policy.common.parameters.annotations.NotBlank;
-import org.onap.policy.common.parameters.annotations.NotNull;
/**
* Class to hold topic details such as name, server and topicCommInfrastructure.
*
* @author Ajith Sreekumar (ajith.sreekumar@est.tech)
*/
-@NotNull
-@NotBlank
@Getter
@Setter
@EqualsAndHashCode(callSuper = false)
public class TopicParameters extends BusTopicParams {
+ @NotBlank
private String topicCommInfrastructure;
public TopicParameters() {
+++ /dev/null
-/*-
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2024 Nordix Foundation
- * ================================================================================
- * 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 static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Consumer;
-import lombok.Getter;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-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.Pattern;
-import org.onap.policy.common.parameters.annotations.Valid;
-
-class TestBeanValidator {
- private static final String TOP = "top";
- private static final String STR_FIELD = "strValue";
- private static final String INT_FIELD = "intValue";
- private static final String NUM_FIELD = "numValue";
- private static final String STRING_VALUE = "string value";
- private static final int INT_VALUE = 20;
-
- private BeanValidator validator;
-
- @BeforeEach
- void setUp() {
- validator = new BeanValidator();
- }
-
- @Test
- void testValidateTop_testValidateFields() {
- // validate null
- assertTrue(validator.validateTop(TOP, null).isValid());
-
- // validate something that has no annotations
- assertTrue(validator.validateTop(TOP, validator).isValid());
-
- @NotNull
- @Getter
- class Data {
- String strValue;
- }
-
- // one failure case
- Data data = new Data();
- BeanValidationResult result = validator.validateTop(TOP, data);
- assertInvalid("testValidateFields", result, STR_FIELD, "null");
- assertTrue(result.getResult().contains(TOP));
-
- // one success case
- data.strValue = STRING_VALUE;
- assertTrue(validator.validateTop(TOP, data).isValid());
-
- @Getter
- class Derived extends Data {
- @Min(10)
- int intValue;
- }
-
- Derived derived = new Derived();
- derived.strValue = STRING_VALUE;
- derived.intValue = INT_VALUE;
-
- // success case
- assertTrue(validator.validateTop(TOP, derived).isValid());
-
- // failure cases
- derived.strValue = null;
- assertInvalid("testValidateFields", validator.validateTop(TOP, derived), STR_FIELD, "null");
- derived.strValue = STRING_VALUE;
-
- derived.intValue = 1;
- assertInvalid("testValidateFields", validator.validateTop(TOP, derived), INT_FIELD, "minimum");
- derived.intValue = INT_VALUE;
-
- // both invalid
- derived.strValue = null;
- derived.intValue = 1;
- result = validator.validateTop(TOP, derived);
- assertInvalid("testValidateFields", result, STR_FIELD, "null");
- assertInvalid("testValidateFields", result, INT_FIELD, "minimum");
- derived.strValue = STRING_VALUE;
- derived.intValue = INT_VALUE;
- }
-
- @Test
- void testVerNotNull() {
- @Getter
- class NotNullCheck {
- @Min(1)
- @NotNull
- Integer intValue;
- }
-
- NotNullCheck notNullCheck = new NotNullCheck();
- assertInvalid("testVerNotNull", validator.validateTop(TOP, notNullCheck), INT_FIELD, "null");
-
- notNullCheck.intValue = INT_VALUE;
- assertTrue(validator.validateTop(TOP, notNullCheck).isValid());
-
- notNullCheck.intValue = 0;
- assertInvalid("testVerNotNull", validator.validateTop(TOP, notNullCheck), INT_FIELD, "minimum");
- }
-
- @Test
- void testVerNotBlank() {
- @Getter
- class NotBlankCheck {
- @NotBlank
- String strValue;
- }
-
- NotBlankCheck notBlankCheck = new NotBlankCheck();
-
- // null
- assertTrue(validator.validateTop(TOP, notBlankCheck).isValid());
-
- // empty
- notBlankCheck.strValue = "";
- assertInvalid("testVerNotNull", validator.validateTop(TOP, notBlankCheck), STR_FIELD, "blank");
-
- // spaces
- notBlankCheck.strValue = " ";
- assertInvalid("testVerNotNull", validator.validateTop(TOP, notBlankCheck), STR_FIELD, "blank");
-
- // not blank
- notBlankCheck.strValue = STRING_VALUE;
- assertTrue(validator.validateTop(TOP, notBlankCheck).isValid());
-
- /*
- * Class with "blank" annotation on an integer.
- */
- @Getter
- class NotBlankInt {
- @NotBlank
- int intValue;
- }
-
- NotBlankInt notBlankInt = new NotBlankInt();
- notBlankInt.intValue = 0;
- assertTrue(validator.validateTop(TOP, notBlankInt).isValid());
- }
-
- @Test
- void testVerRegex() {
- @Getter
- class RegexCheck {
- @Pattern(regexp = "[a-f]*")
- String strValue;
- }
-
- RegexCheck regexCheck = new RegexCheck();
-
- // does not match
- regexCheck.strValue = "xyz";
- assertInvalid("testVerRegex", validator.validateTop(TOP, regexCheck), STR_FIELD,
- "does not match regular expression [a-f]");
-
- // matches
- regexCheck.strValue = "abcabc";
- assertTrue(validator.validateTop(TOP, regexCheck).isValid());
-
- // invalid regex
- @Getter
- class InvalidRegexCheck {
- @Pattern(regexp = "[a-f")
- String strValue;
- }
-
- InvalidRegexCheck invalidRegexCheck = new InvalidRegexCheck();
-
- // does not match
- invalidRegexCheck.strValue = "abc";
- assertInvalid("testVerRegex", validator.validateTop(TOP, invalidRegexCheck), STR_FIELD,
- "does not match regular expression [a-f");
-
- // matches
- regexCheck.strValue = "abcabc";
- assertTrue(validator.validateTop(TOP, regexCheck).isValid());
-
- /*
- * Class with "regex" annotation on an integer.
- */
- @Getter
- class RegexInt {
- @Pattern(regexp = "[a-f]*")
- int intValue;
- }
-
- RegexInt regexInt = new RegexInt();
- regexInt.intValue = 0;
- assertInvalid("testVerRegex", validator.validateTop(TOP, regexInt), INT_FIELD,
- "does not match regular expression [a-f]");
- }
-
- @Test
- void testVerMin() {
- /*
- * Field is not a number.
- */
- @Getter
- class NonNumeric {
- @Min(10)
- String strValue;
- }
-
- NonNumeric nonNumeric = new NonNumeric();
- nonNumeric.strValue = STRING_VALUE;
- assertTrue(validator.validateTop(TOP, nonNumeric).isValid());
-
- /*
- * Integer field.
- */
- @Getter
- class IntField {
- @Min(10)
- Integer intValue;
- }
-
- // ok value
- IntField intField = new IntField();
- assertNumeric(intField, value -> {
- intField.intValue = value;
- }, INT_FIELD, "minimum", 10, 1);
-
- /*
- * Long field.
- */
- @Getter
- class LongField {
- @Min(10)
- Long numValue;
- }
-
- // ok value
- LongField longField = new LongField();
- assertNumeric(longField, value -> {
- longField.numValue = (long) value;
- }, NUM_FIELD, "minimum", 10, 1);
-
- /*
- * Float field.
- */
- @Getter
- class FloatField {
- @Min(10)
- Float numValue;
- }
-
- // ok value
- FloatField floatField = new FloatField();
- assertNumeric(floatField, value -> {
- floatField.numValue = (float) value;
- }, NUM_FIELD, "minimum", 10, 1);
-
- /*
- * Double field.
- */
- @Getter
- class DoubleField {
- @Min(10)
- Double numValue;
- }
-
- // ok value
- DoubleField doubleField = new DoubleField();
- assertNumeric(doubleField, value -> {
- doubleField.numValue = (double) value;
- }, NUM_FIELD, "minimum", 10, 1);
-
- /*
- * Atomic Integer field (which is a subclass of Number).
- */
- @Getter
- class AtomIntValue {
- @Min(10)
- AtomicInteger numValue;
- }
-
- // ok value
- AtomIntValue atomIntField = new AtomIntValue();
- atomIntField.numValue = new AtomicInteger(INT_VALUE);
- assertTrue(validator.validateTop(TOP, atomIntField).isValid());
-
- // invalid value - should be OK, because it isn't an Integer
- atomIntField.numValue.set(101);
- assertTrue(validator.validateTop(TOP, atomIntField).isValid());
- }
-
- @Test
- void testVerCascade() {
- @Getter
- class Item {
- @NotNull
- Integer intValue;
- }
-
- @Getter
- class Container {
- @Valid
- Item checked;
-
- Item unchecked;
-
- @Valid
- List<Item> items;
-
- @Valid
- Map<String, Item> itemMap;
- }
-
- Container cont = new Container();
- cont.unchecked = new Item();
- cont.items = List.of(new Item());
- cont.itemMap = Map.of(STRING_VALUE, new Item());
-
- cont.checked = null;
- assertTrue(validator.validateTop(TOP, cont).isValid());
-
- cont.checked = new Item();
-
- assertInvalid("testVerCascade", validator.validateTop(TOP, cont), INT_FIELD, "null");
-
- cont.checked.intValue = INT_VALUE;
- assertTrue(validator.validateTop(TOP, cont).isValid());
- }
-
- @Test
- void testVerCollection() {
- @Getter
- class Container {
- List<@Min(5) Integer> items;
-
- // not a collection - should not be checked
- @Valid
- String strValue;
-
- String noAnnotations;
- }
-
- Container cont = new Container();
- cont.strValue = STRING_VALUE;
- cont.noAnnotations = STRING_VALUE;
-
- // null collection - always valid
- assertTrue(validator.validateTop(TOP, cont).isValid());
-
- // empty collection - always valid
- cont.items = List.of();
- assertTrue(validator.validateTop(TOP, cont).isValid());
-
- cont.items = List.of(-10, -20);
- assertThat(validator.validateTop(TOP, cont).getResult()).contains("\"0\"", "-10", "\"1\"", "-20", "minimum");
-
- cont.items = List.of(10, -30);
- assertThat(validator.validateTop(TOP, cont).getResult()).contains("\"1\"", "-30", "minimum")
- .doesNotContain("\"0\"");
-
- cont.items = List.of(10, 20);
- assertTrue(validator.validateTop(TOP, cont).isValid());
- }
-
- @Test
- void testVerMap() {
- @Getter
- class Container {
- Map<String, @Min(5) Integer> items;
-
- // not a map
- @NotBlank
- String strValue;
-
- String noAnnotations;
- }
-
- Container cont = new Container();
- cont.strValue = STRING_VALUE;
- cont.noAnnotations = STRING_VALUE;
-
- // null map - always valid
- assertTrue(validator.validateTop(TOP, cont).isValid());
-
- // empty map - always valid
- cont.items = Map.of();
- assertTrue(validator.validateTop(TOP, cont).isValid());
-
- cont.items = Map.of("abc", -10, "def", -20);
- assertThat(validator.validateTop(TOP, cont).getResult()).contains("abc", "-10", "def", "-20", "minimum");
-
- cont.items = Map.of("abc", 10, "def", -30);
- assertThat(validator.validateTop(TOP, cont).getResult()).contains("def", "-30", "minimum")
- .doesNotContain("abc");
-
- cont.items = Map.of("abc", 10, "def", 20);
- assertTrue(validator.validateTop(TOP, cont).isValid());
- }
-
- @Test
- void testGetEntryName() {
- assertThat(validator.getEntryName(makeEntry(null))).isEmpty();
- assertThat(validator.getEntryName(makeEntry(""))).isEmpty();
- assertThat(validator.getEntryName(makeEntry(STRING_VALUE))).isEqualTo(STRING_VALUE);
- }
-
- /**
- * Makes a Map entry with the given key and value.
- *
- * @param key desired key
- * @return a new Map entry
- */
- private Map.Entry<String, Integer> makeEntry(String key) {
- HashMap<String, Integer> map = new HashMap<>();
- map.put(key, 0);
- return map.entrySet().iterator().next();
- }
-
- private <T> void assertNumeric(T object, Consumer<Integer> setter, String fieldName,
- String expectedText, int edge, int outside) {
- setter.accept(TestBeanValidator.INT_VALUE);
- assertTrue(validator.validateTop(TOP, object).isValid());
-
- // on the edge
- setter.accept(edge);
- assertTrue(validator.validateTop(TOP, object).isValid());
-
- // invalid
- setter.accept(outside);
- assertInvalid("testVerNotNull", validator.validateTop(TOP, object), fieldName, expectedText);
- }
-
-
- private void assertInvalid(String testName, BeanValidationResult result, String... text) {
- assertThat(result.getResult()).describedAs(testName).contains(text);
- }
-}
+++ /dev/null
-/*-
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2023-2025 OpenInfra Foundation Europe. 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 static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-import com.google.gson.annotations.SerializedName;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.util.List;
-import java.util.Map;
-import lombok.Getter;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.onap.policy.common.parameters.annotations.Min;
-import org.onap.policy.common.parameters.annotations.NotBlank;
-import org.onap.policy.common.parameters.annotations.NotNull;
-
-class TestFieldValidator extends ValidatorUtil {
- private static final String INT_LIST_FIELD = "intList";
- private static final String INT_MAP_FIELD = "intMap";
- private static final String UNANNOTATED_FIELD = "unannotated";
- private static final String INT_FIELD = "intValue";
- private static final int VALID_INT = 10;
- private static final int INVALID_INT = -10;
-
- @Getter
- private int unannotated;
-
- @Min(0)
- @Getter
- private int intValue;
-
- @Getter
- private List<@Min(1) Integer> intList;
-
- @Getter
- private Map<@NotBlank String, @Min(1) Integer> intMap;
-
- @SerializedName("annotated_key_map")
- @Getter
- private Map<@NotBlank String, Integer> annotatedKeyMap;
-
- @Getter
- private Map<String, @Min(1) Integer> annotatedValueMap;
-
- @Getter
- private List<Integer> unannotatedList;
-
- @Getter
- private Map<String, Integer> unannotatedMap;
-
- @NotNull
- @Getter
- private boolean boolValue;
-
- @NotNull
- @Getter
- private String notNullValue;
-
- @Min(0)
- @Getter
- private static int staticField;
-
- /**
- * Has no accessor.
- */
- @Min(0)
- private int noMethod;
-
- /**
- * Accessor is {@link #getStaticMethod()}, which is static.
- */
- @Min(0)
- private int staticMethod;
-
- /**
- * Accessor is {@link #getVoidMethod()}, which returns a void.
- */
- @Min(0)
- private int voidMethod;
-
- /**
- * Accessor is {@link #getParameterizedMethod(boolean)}, which requires a parameter.
- */
- @Min(0)
- private int parameterizedMethod;
-
- /**
- * Accessor is {@link #getExMethod()}, which throws an exception.
- */
- @Min(0)
- private int exMethod;
-
-
- @BeforeEach
- void setUp() {
- bean = new BeanValidator();
- }
-
- @Test
- void testGetAnnotation() {
- // field-level annotation
- assertThat(new FieldValidator(bean, TestFieldValidator.class, getField(INT_FIELD)).isEmpty()).isFalse();
-
- // class-level annotation
- assertThat(new FieldValidator(bean, ClassAnnot.class, getField(ClassAnnot.class, "text")).isEmpty()).isFalse();
- }
-
- @Test
- void testFieldValidator() throws SecurityException {
- /*
- * Class with no annotations.
- */
- @NotNull
- class NoAnnotations {
- @SuppressWarnings("unused")
- String strValue;
- }
-
- // unannotated
- assertThat(new FieldValidator(bean, TestFieldValidator.class, getField("unannotated")).isEmpty()).isTrue();
-
- // these are invalid for various reasons
-
- Field staticField2 = getField("staticField");
- assertThatThrownBy(() -> new FieldValidator(bean, TestFieldValidator.class, staticField2))
- .isInstanceOf(IllegalArgumentException.class);
-
- Field noMethodField = getField("noMethod");
- assertThatThrownBy(() -> new FieldValidator(bean, TestFieldValidator.class, noMethodField))
- .isInstanceOf(IllegalArgumentException.class);
-
- // annotated
- assertThat(new FieldValidator(bean, TestFieldValidator.class, getField(INT_FIELD)).isEmpty()).isFalse();
- }
-
- @Test
- void testFieldValidator_SetNullAllowed() {
- // default - null is allowed
- assertThat(new FieldValidator(bean, TestFieldValidator.class, getField(INT_FIELD)).isNullAllowed()).isTrue();
-
- // field-level NotNull
- assertThat(new FieldValidator(bean, TestFieldValidator.class, getField("notNullValue")).isNullAllowed())
- .isFalse();
-
- // class-level NotNull
- assertThat(new FieldValidator(bean, ClassAnnot.class, getField(ClassAnnot.class, "noMethod")).isNullAllowed())
- .isFalse();
- }
-
- @Test
- void testAddListValidator() {
-
- // unannotated
- assertThat(new FieldValidator(bean, TestFieldValidator.class, getField("unannotatedList")).isEmpty()).isTrue();
-
- // annotated
- assertThat(new FieldValidator(bean, TestFieldValidator.class, getField(INT_LIST_FIELD)).isEmpty()).isFalse();
- }
-
- @Test
- void testAddMapValidator() {
-
- // unannotated
- assertThat(new FieldValidator(bean, TestFieldValidator.class, getField("unannotatedMap")).isEmpty()).isTrue();
-
- // annotated
- assertThat(new FieldValidator(bean, TestFieldValidator.class, getField(INT_MAP_FIELD)).isEmpty()).isFalse();
-
- // only the key is annotated
- FieldValidator validator = new FieldValidator(bean, TestFieldValidator.class, getField("annotatedKeyMap"));
- assertThat(validator.isEmpty()).isFalse();
-
- BeanValidationResult result = new BeanValidationResult(MY_NAME, this);
- annotatedKeyMap = Map.of("abc", -10);
- validator.validateField(result, this);
- assertThat(result.getResult()).isNull();
-
- annotatedKeyMap = Map.of(" ", -10);
- validator.validateField(result, this);
- assertThat(result.getResult()).contains("annotated_key_map", "blank").doesNotContain("-10");
-
- // only the value is annotated
- validator = new FieldValidator(bean, TestFieldValidator.class, getField("annotatedValueMap"));
- assertThat(validator.isEmpty()).isFalse();
-
- result = new BeanValidationResult(MY_NAME, this);
- annotatedValueMap = Map.of(" ", 10);
- validator.validateField(result, this);
- assertThat(result.getResult()).isNull();
-
- annotatedValueMap = Map.of(" ", -10);
- validator.validateField(result, this);
- assertThat(result.getResult()).doesNotContain("blank").contains("annotatedValueMap", "\" \"", "-10");
- }
-
- @SuppressWarnings("deprecation")
- @Test
- void testValidateField_testGetValue() {
- // unannotated
- BeanValidationResult result = new BeanValidationResult(MY_NAME, this);
- new FieldValidator(bean, getClass(), getField(UNANNOTATED_FIELD)).validateField(result, this);
- assertThat(result.getResult()).isNull();
-
- // valid
- intValue = VALID_INT;
- result = new BeanValidationResult(MY_NAME, this);
- new FieldValidator(bean, getClass(), getField(INT_FIELD)).validateField(result, this);
- assertThat(result.getResult()).isNull();
-
- // invalid
- intValue = INVALID_INT;
- result = new BeanValidationResult(MY_NAME, this);
- new FieldValidator(bean, getClass(), getField(INT_FIELD)).validateField(result, this);
- assertThat(result.getResult()).contains(INT_FIELD);
-
- // throws an exception
- FieldValidator validator = new FieldValidator(bean, TestFieldValidator.class, getField("exMethod"));
- BeanValidationResult result2 = new BeanValidationResult(MY_NAME, this);
- assertThatThrownBy(() -> validator.validateField(result2, this)).isInstanceOf(IllegalArgumentException.class)
- .getCause().isInstanceOf(InvocationTargetException.class).getCause()
- .hasMessage("expected exception");
- }
-
- @Test
- void testValidateField_testGetValue_ListField() {
- // valid
- BeanValidationResult result = new BeanValidationResult(MY_NAME, this);
- intList = List.of(10, 20, 30, 40);
- new FieldValidator(bean, getClass(), getField(INT_LIST_FIELD)).validateField(result, this);
- assertThat(result.getResult()).isNull();
-
- // invalid
- result = new BeanValidationResult(MY_NAME, this);
- intList = List.of(9, -8, 7, -6);
- new FieldValidator(bean, getClass(), getField(INT_LIST_FIELD)).validateField(result, this);
- assertThat(result.getResult()).doesNotContain("0", "9").contains("1", "-8").doesNotContain("2", "7")
- .contains("3", "-6");
- }
-
- @Test
- void testValidateField_testGetValue_MapField() {
- // valid
- BeanValidationResult result = new BeanValidationResult(MY_NAME, this);
- intMap = Map.of("ten", 10, "twenty", 20, "thirty", 30, "forty", 40);
- new FieldValidator(bean, getClass(), getField(INT_MAP_FIELD)).validateField(result, this);
- assertThat(result.getResult()).isNull();
-
- // invalid
- result = new BeanValidationResult(MY_NAME, this);
- intMap = Map.of("ten", 9, "twenty", -8, "thirty", 7, "forty", -6);
- new FieldValidator(bean, getClass(), getField(INT_MAP_FIELD)).validateField(result, this);
- assertThat(result.getResult()).doesNotContain("ten", "9").contains("twenty", "-8").doesNotContain("thirty", "7")
- .contains("forty", "-6");
- }
-
- @Test
- void testClassOnly() {
- // class-level annotation has no bearing on a static field
- assertThat(new FieldValidator(bean, ClassAnnot.class, getField(ClassAnnot.class, "staticValue")).isEmpty())
- .isTrue();
-
- // field-level annotation on a static field
- Field staticField2 = getField("staticField");
- assertThatThrownBy(() -> new FieldValidator(bean, TestFieldValidator.class, staticField2))
- .isInstanceOf(IllegalArgumentException.class);
- }
-
- @Test
- void testGetAccessor() {
- // uses "getXxx"
- assertThat(new FieldValidator(bean, TestFieldValidator.class, getField(INT_FIELD)).isEmpty()).isFalse();
-
- // uses "isXxx"
- assertThat(new FieldValidator(bean, TestFieldValidator.class, getField("boolValue")).isEmpty()).isFalse();
- }
-
- @Test
- void testGetMethod() {
- assertThat(new FieldValidator(bean, TestFieldValidator.class, getField(INT_FIELD)).isEmpty()).isFalse();
-
- // these are invalid for various reasons
-
- Field noMethodField = getField("noMethod");
- assertThatThrownBy(() -> new FieldValidator(bean, TestFieldValidator.class, noMethodField))
- .isInstanceOf(IllegalArgumentException.class);
-
- Field staticMethodField = getField("staticMethod");
- assertThatThrownBy(() -> new FieldValidator(bean, TestFieldValidator.class, staticMethodField))
- .isInstanceOf(IllegalArgumentException.class);
- }
-
- @Test
- void testValidMethod() {
- assertThat(new FieldValidator(bean, TestFieldValidator.class, getField(INT_FIELD)).isEmpty()).isFalse();
-
- // these are invalid for various reasons
-
- Field staticMethodField = getField("staticMethod");
- assertThatThrownBy(() -> new FieldValidator(bean, TestFieldValidator.class, staticMethodField))
- .isInstanceOf(IllegalArgumentException.class);
-
- Field voidMethodField = getField("voidMethod");
- assertThatThrownBy(() -> new FieldValidator(bean, TestFieldValidator.class, voidMethodField))
- .isInstanceOf(IllegalArgumentException.class);
-
- Field paramMethodField = getField("parameterizedMethod");
- assertThatThrownBy(() -> new FieldValidator(bean, TestFieldValidator.class, paramMethodField))
- .isInstanceOf(IllegalArgumentException.class);
- }
-
- @Test
- void testIsFieldAnnotated_testSetFieldAnnotated() {
- // annotated at the field level
- assertThat(new FieldValidator(bean, getClass(), getField(INT_FIELD)).isFieldAnnotated()).isTrue();
-
- // unannotated
- assertThat(new FieldValidator(bean, getClass(), getField(UNANNOTATED_FIELD)).isFieldAnnotated()).isFalse();
- }
-
- public static int getStaticMethod() {
- return -1000;
- }
-
- void getVoidMethod() {
- // do nothing
- }
-
- public int getParameterizedMethod(boolean flag) {
- return flag ? 0 : 1;
- }
-
- public int getExMethod() {
- throw new RuntimeException("expected exception");
- }
-
- @NotNull
- public static class ClassAnnot {
- @Getter
- private String text;
-
- // no "get" method
- @SuppressWarnings("unused")
- private String noMethod;
-
- @Getter
- private static int staticValue;
- }
-}
+++ /dev/null
-/*-
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2024 Nordix Foundation
- * ================================================================================
- * 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 static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.onap.policy.common.parameters.annotations.Min;
-import org.onap.policy.common.parameters.annotations.NotBlank;
-import org.onap.policy.common.parameters.annotations.NotNull;
-
-class TestItemValidator extends ValidatorUtil {
-
- // annotated fields - each field must have exactly one annotation
-
- /**
- * This annotation does not contain a method returning an array.
- */
- @Min(value = 0)
- private int notArray;
-
- /**
- * This annotation doesn't contain any annotations that the {@link BeanValidator}
- * recognizes.
- */
- @Simple
- private int mismatch;
-
- /**
- * No annotations.
- */
- @SuppressWarnings("unused")
- private int noAnnotations;
-
- /**
- * One matching annotation.
- */
- @NotNull
- private int match;
-
- /**
- * Multiple matching annotations.
- */
- @NotNull
- @NotBlank
- private String multiMatch;
-
-
- @BeforeEach
- void setUp() {
- bean = new BeanValidator();
- }
-
- @Test
- void testGetAnnotation() {
- // no matches
- assertThat(new ItemValidator(bean, getAnnotType("noAnnotations"), true).isEmpty()).isTrue();
-
- // had a match
- assertThat(new ItemValidator(bean, getAnnotType("match"), true).checkers).hasSize(1);
-
- // multiple matches
- ItemValidator validator = new ItemValidator(bean, getAnnotType("multiMatch"), true);
- assertThat(validator.checkers).hasSize(2);
-
- BeanValidationResult result = new BeanValidationResult(MY_NAME, this);
- validator.validateValue(result, MY_FIELD, HELLO);
- assertThat(result.getResult()).isNull();
-
- result = new BeanValidationResult(MY_NAME, this);
- validator.validateValue(result, MY_FIELD, null);
- assertThat(result.getResult()).isNotNull();
-
- result = new BeanValidationResult(MY_NAME, this);
- validator.validateValue(result, MY_FIELD, "");
- assertThat(result.getResult()).isNotNull();
- }
-
- @Test
- void testItemValidatorBeanValidatorAnnotation() {
- assertThat(new ItemValidator(bean, getAnnotType("match")).isEmpty()).isFalse();
- }
-
- @Test
- void testItemValidatorBeanValidatorAnnotationBoolean() {
- assertThat(new ItemValidator(bean, getAnnotType("match"), true).isEmpty()).isFalse();
-
- assertThat(new ItemValidator(bean, getAnnotType("match"), false).isEmpty()).isTrue();
- }
-
- // these annotations are not recognized by the BeanValidator
-
- @Retention(RUNTIME)
- @Target(FIELD)
- public @interface Simple {
-
- }
-}
+++ /dev/null
-/*-
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2024-2025 Nordix Foundation
- * ================================================================================
- * 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 static org.assertj.core.api.Assertions.assertThat;
-
-import java.lang.annotation.Annotation;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.onap.policy.common.parameters.annotations.Min;
-import org.onap.policy.common.parameters.annotations.NotBlank;
-import org.onap.policy.common.parameters.annotations.NotNull;
-
-class TestValueValidator extends ValidatorUtil {
-
- private ValueValidator validator;
-
- // these fields just provide place-holders for annotations
-
- @NotNull
- @NotBlank
- private final int annotField = 1;
-
-
- @BeforeEach
- void setUp() {
- validator = new MyValueValidator();
- }
-
- @Test
- void testIsEmpty() {
- assertThat(validator.isEmpty()).isTrue();
-
- validator.addAnnotation(NotNull.class, (result2, fieldName, value) -> true);
- assertThat(validator.isEmpty()).isFalse();
- }
-
- @Test
- void testValidateValue_NullValue() {
- BeanValidationResult result = new BeanValidationResult(MY_NAME, this);
-
- validator.validateValue(result, MY_FIELD, null);
- assertThat(result.getResult()).isNull();
-
- validator.addAnnotation(NotNull.class, BeanValidationResult::validateNotNull);
- validator.validateValue(result, MY_FIELD, null);
- assertThat(result.getResult()).contains(MY_FIELD, "null");
- }
-
- @Test
- void testValidateValue_NotNullValue() {
- BeanValidationResult result = new BeanValidationResult(MY_NAME, this);
-
- validator.validateValue(result, MY_FIELD, HELLO);
- assertThat(result.getResult()).isNull();
-
- validator.addAnnotation(NotNull.class, BeanValidationResult::validateNotNull);
- validator.validateValue(result, MY_FIELD, HELLO);
- assertThat(result.getResult()).isNull();
- }
-
- @Test
- void testAddAnnotationClassOfTChecker() {
- // the field does not have this annotation
- validator.addAnnotation(Min.class, (result2, fieldName, value) -> true);
- assertThat(validator.isEmpty()).isTrue();
-
- // "null" flag should stay true with this annotation
- assertThat(validator.isNullAllowed()).isTrue();
- validator.addAnnotation(NotBlank.class, (result2, fieldName, value) -> true);
- assertThat(validator.isNullAllowed()).isTrue();
-
- // "null" flag should become false with this annotation
- validator.addAnnotation(NotNull.class, (result2, fieldName, value) -> true);
- assertThat(validator.isNullAllowed()).isFalse();
- }
-
- @Test
- void testAddAnnotationClassOfTCheckerWithAnnotOfT() {
- // the field does not have this annotation
- validator.addAnnotation(Min.class, (result2, fieldName, annot, value) -> true);
- assertThat(validator.isEmpty()).isTrue();
-
- // indicates the annotation value
- AtomicBoolean wasNull = new AtomicBoolean(false);
-
- // the field DOES have this annotation
- validator.addAnnotation(NotNull.class, (result2, fieldName, annot, value) -> {
- wasNull.set(annot != null);
- return result2.validateNotNull(fieldName, value);
- });
- assertThat(validator.isEmpty()).isFalse();
-
- // ensure that the checker is invoked
- BeanValidationResult result = new BeanValidationResult(MY_NAME, this);
- validator.validateValue(result, MY_FIELD, HELLO);
- assertThat(result.getResult()).isNull();
-
- assertThat(wasNull.get()).isTrue();
- }
-
- @Test
- void testGetAnnotation() {
- assertThat(new ValueValidator().getAnnotation(NotNull.class)).isNull();
- }
-
- /**
- * Checks for annotations on the "annotField" field.
- */
- private static class MyValueValidator extends ValueValidator {
- @Override
- public <T extends Annotation> T getAnnotation(Class<T> annotClass) {
- try {
- return TestValueValidator.class.getDeclaredField("annotField").getAnnotation(annotClass);
- } catch (NoSuchFieldException | SecurityException e) {
- throw new RuntimeException(e);
- }
- }
- }
-}
+++ /dev/null
-/*-
- * ============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.common.parameters;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AnnotatedType;
-import java.lang.reflect.Field;
-
-/**
- * Utilities for validator tests.
- */
-public class ValidatorUtil {
- protected static final String MY_NAME = "My-Name";
- protected static final String MY_FIELD = "My-Field";
- protected static final String HELLO = "hello";
-
- protected BeanValidator bean;
-
- /**
- * Gets the single annotation for a given field.
- *
- * @param fieldName name of the field having the desired annotation
- * @return the given field's annotation
- */
- protected Annotation getAnnot(String fieldName) {
- return getField(fieldName).getAnnotations()[0];
- }
-
- /**
- * Gets the annotated type for a given field.
- *
- * @param fieldName name of the field of interest
- * @return the given field's annotated type
- */
- protected AnnotatedType getAnnotType(String fieldName) {
- return getField(fieldName).getAnnotatedType();
- }
-
- /**
- * Gets a field from this object.
- *
- * @param fieldName name of the field of interest
- * @return the given field
- */
- protected Field getField(String fieldName) {
- return getField(getClass(), fieldName);
- }
-
- /**
- * Gets a field from a given class.
- *
- * @param clazz class containing the field
- * @param fieldName name of the field of interest
- * @return the given field
- */
- protected Field getField(Class<?> clazz, String fieldName) {
- try {
- return clazz.getDeclaredField(fieldName);
-
- } catch (NoSuchFieldException | SecurityException e) {
- throw new RuntimeException(e);
- }
- }
-
-}
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2019 Nordix Foundation.
+ * Copyright (C) 2019-2026 OpenInfra Foundation Europe. 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");
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
+import jakarta.validation.constraints.Pattern;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import lombok.ToString;
-import org.onap.policy.common.parameters.annotations.Pattern;
import org.onap.policy.common.utils.validation.Assertions;
/**
+++ /dev/null
-/*-
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2023-2024 Nordix Foundation.
- * ================================================================================
- * 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 org.onap.policy.common.parameters.BeanValidationResult;
-import org.onap.policy.common.parameters.BeanValidator;
-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.VerifyKey;
-
-public class PfValidator extends BeanValidator {
-
- @Override
- protected void addValidators(ValueValidator validator) {
- super.addValidators(validator);
-
- validator.addAnnotation(VerifyKey.class, this::verKey);
- }
-
- /**
- * 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 validated) {
- ValidationResult result2 = validated.validate(fieldName);
- if (result2 == null) {
- return true;
- }
-
- if (!result2.isClean()) {
- 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 pfkey)) {
- return true;
- }
-
- if (annot.keyNotNull() && pfkey.isNullKey()) {
- result.addResult(fieldName, xlate(pfkey), ValidationStatus.INVALID, Validated.IS_A_NULL_KEY);
- return false;
- }
-
- if (annot.valid()) {
- verCascade(result, fieldName, value);
- }
-
- if (!(pfkey instanceof PfKeyImpl keyimpl)) {
- return true;
- }
-
- var result2 = new BeanValidationResult(fieldName, value);
-
- if (annot.nameNotNull() && keyimpl.isNullName()) {
- result2.addResult("name", pfkey.getName(), ValidationStatus.INVALID, Validated.IS_NULL);
- }
-
- if (annot.versionNotNull() && keyimpl.isNullVersion()) {
- result2.addResult("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 ? pfKey.getId() : value);
- }
-}
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2024 Nordix Foundation
+ * Modifications Copyright (C) 2024-2026 OpenInfra Foundation Europe. 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.
import lombok.NonNull;
import org.onap.policy.common.parameters.BeanValidationResult;
-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.BeanValidator;
/**
* Classes that can be validated. This can be used as a super class or as a stand-alone
* utility class.
*/
public class Validated {
- public static final String IS_A_NULL_KEY = "is a null key";
- public static final String IS_NULL = "is null";
public static final String NOT_FOUND = "not found";
- public static final String KEY_TOKEN = "key";
- public static final String VALUE_TOKEN = "value";
/**
- * Validates the fields of the object. The default method uses a {@link PfValidator}
+ * Validates the fields of the object. The default method uses a {@link BeanValidator}
* to validate the object.
*
* @param fieldName name of the field containing this
* @return the result, or {@code null}
*/
- public BeanValidationResult validate(@NonNull String fieldName) {
- return new PfValidator().validateTop(fieldName, this);
- }
-
- /**
- * Adds a result indicating that a value is invalid.
- *
- * @param result where to put the result
- * @param fieldName name of the field containing the value
- * @param value the field's value
- * @param errorMessage the error message
- */
- public static void addResult(@NonNull BeanValidationResult result, @NonNull String fieldName, Object value,
- @NonNull String errorMessage) {
- result.addResult(fieldName, getKeyId(value), ValidationStatus.INVALID, errorMessage);
- }
-
- /**
- * Makes a result that indicates a value is invalid, because it is null.
- *
- * @param fieldName name of the field containing the value
- * @param value the field's value
- * @return a result indicating the value is invalid
- */
- public static ValidationResult makeNullResult(@NonNull String fieldName, Object value) {
- return new ObjectValidationResult(fieldName, getKeyId(value), ValidationStatus.INVALID, IS_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
- */
- public static void validateKeyNotNull(BeanValidationResult result, @NonNull String fieldName, PfKey key) {
- if (key == null) {
- result.addResult(fieldName, key, ValidationStatus.INVALID, IS_A_NULL_KEY);
- return;
- }
-
- if (key.isNullKey()) {
- result.addResult(fieldName, key.getId(), ValidationStatus.INVALID, IS_A_NULL_KEY);
- return;
- }
-
- 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
- */
- public static void validateKeyVersionNotNull(BeanValidationResult result, @NonNull String fieldName,
- PfConceptKey key) {
- if (key != null && key.isNullVersion()) {
- var result2 = new BeanValidationResult(fieldName, key);
- result2.addResult(makeNullResult(PfKeyImpl.VERSION_TOKEN, key.getVersion()));
- result.addResult(result2);
- }
- }
-
- /**
- * Gets a key's ID, if the value is a {@link PfKey}.
- *
- * @param value value from which to get the ID
- * @return the value's ID, if it's a key, the original value otherwise
- */
- private static Object getKeyId(Object value) {
- return (value instanceof PfKey pfKey ? pfKey.getId() : value);
+ public final BeanValidationResult validate(@NonNull String fieldName) {
+ return BeanValidator.validate(fieldName, this);
}
}
/*-
* ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
* Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2026 OpenInfra Foundation Europe. 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.
* 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
* ============LICENSE_END=========================================================
*/
package org.onap.policy.models.base.validation.annotations;
import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
/**
- * Validates a key.
+ * Verifies a key is not a null key. Note @Valid annotation should also be used with this one to fully validate the key.
*/
@Retention(RUNTIME)
-@Target(FIELD)
+@Target({FIELD, METHOD})
+@Constraint(validatedBy = VerifyKeyValidator.class)
public @interface VerifyKey {
/**
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.
+ * The error message template.
+ */
+ String message() default "Key validation failed";
+
+ /**
+ * The groups the constraint belongs to.
+ */
+ Class<?>[] groups() default {};
+
+ /**
+ * The payload associated to the constraint.
*/
- boolean valid() default true;
+ Class<? extends Payload>[] payload() default {};
}
--- /dev/null
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2026 OpenInfra Foundation Europe. 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base.validation.annotations;
+
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+import org.onap.policy.models.base.PfKey;
+import org.onap.policy.models.base.PfKeyImpl;
+
+public class VerifyKeyValidator implements ConstraintValidator<VerifyKey, PfKey> {
+
+ private VerifyKey annotation;
+
+ @Override
+ public void initialize(VerifyKey constraintAnnotation) {
+ this.annotation = constraintAnnotation;
+ }
+
+ @Override
+ public boolean isValid(PfKey pfkey, ConstraintValidatorContext context) {
+ if (pfkey == null) {
+ return true;
+ }
+
+ context.disableDefaultConstraintViolation();
+ boolean valid = true;
+
+ if (annotation.keyNotNull() && pfkey.isNullKey()) {
+ context.buildConstraintViolationWithTemplate("is a null key").addConstraintViolation();
+ return false;
+ }
+
+ if (pfkey instanceof PfKeyImpl keyimpl) {
+ if (annotation.nameNotNull() && keyimpl.isNullName()) {
+ context.buildConstraintViolationWithTemplate("is null")
+ .addPropertyNode("name").addConstraintViolation();
+ valid = false;
+ }
+
+ if (annotation.versionNotNull() && keyimpl.isNullVersion()) {
+ context.buildConstraintViolationWithTemplate("is null")
+ .addPropertyNode("version").addConstraintViolation();
+ valid = false;
+ }
+ }
+
+ return valid;
+ }
+}
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import jakarta.validation.constraints.Pattern;
import java.lang.reflect.Field;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import org.onap.policy.common.parameters.BeanValidator;
import org.onap.policy.common.parameters.ValidationResult;
-import org.onap.policy.common.parameters.annotations.Pattern;
import org.onap.policy.models.base.PfKey.Compatibility;
class PfKeyImplTest {
nameField.set(testKey, "TheKey");
nameField.setAccessible(false);
assertThat(validationResult.getResult()).contains("\"name\"").doesNotContain("\"version\"")
- .contains("does not match regular expression " + PfKey.NAME_REGEXP);
+ .contains("must match \"" + PfKey.NAME_REGEXP + "\"");
Field versionField = testKey.getClass().getDeclaredField("version");
versionField.setAccessible(true);
versionField.set(testKey, VERSION001);
versionField.setAccessible(false);
assertThat(validationResult2.getResult()).doesNotContain("\"name\"").contains("\"version\"")
- .contains("does not match regular expression " + PfKey.VERSION_REGEXP);
+ .contains("must match \"" + PfKey.VERSION_REGEXP + "\"");
}
@Getter
+++ /dev/null
-/*-
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2023, 2024 Nordix Foundation.
- * ================================================================================
- * 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 jakarta.validation.Valid;
-import java.io.Serial;
-import java.util.concurrent.atomic.AtomicBoolean;
-import lombok.Getter;
-import lombok.NonNull;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.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.VerifyKey;
-
-class PfValidatorTest {
- private static final String KEY_FIELD = "key";
-
- private static final String STRING_VALUE = "abc";
-
- private PfValidator validator;
-
- @BeforeEach
- void setUp() {
- validator = new PfValidator();
- }
-
- @Test
- 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
- 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
- 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() {
- @Serial
- 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
- 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 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;
- }
-}
+++ /dev/null
-/*-
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2024 Nordix Foundation
- * ================================================================================
- * 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.assertj.core.api.Assertions.assertThatCode;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-
-import lombok.AllArgsConstructor;
-import lombok.NonNull;
-import org.junit.jupiter.api.Test;
-import org.onap.policy.common.parameters.BeanValidationResult;
-import org.onap.policy.common.parameters.ValidationResult;
-import org.onap.policy.common.parameters.ValidationStatus;
-import org.onap.policy.common.utils.coder.CoderException;
-import org.onap.policy.common.utils.coder.StandardCoder;
-
-class ValidatedTest {
- private static final @NonNull String MY_FIELD = "myField";
- private static final @NonNull String Q_KEY = "\"" + Validated.KEY_TOKEN + "\"";
- private static final @NonNull String Q_VALUE = "\"" + Validated.VALUE_TOKEN + "\"";
- private static final String NOT_SAME = "not same";
- private static final String TEXT = "some text";
- private static final String OTHER = "other text";
- private static final String NAME = "myKey";
- private static final String VERSION = "1.0.0";
-
- @Test
- void testAddResult() {
- BeanValidationResult result = new BeanValidationResult("", this);
- Validated.addResult(result, MY_FIELD, TEXT, "some message");
- assertThat(result.getResult()).contains(MY_FIELD).contains(TEXT).contains("some message");
-
- assertThatThrownBy(() -> Validated.addResult(null, MY_FIELD, TEXT, OTHER))
- .isInstanceOf(NullPointerException.class);
-
- assertThatThrownBy(() -> Validated.addResult(result, null, TEXT, OTHER))
- .isInstanceOf(NullPointerException.class);
-
- assertThatCode(() -> Validated.addResult(result, MY_FIELD, null, OTHER)).doesNotThrowAnyException();
-
- assertThatThrownBy(() -> Validated.addResult(result, MY_FIELD, TEXT, null))
- .isInstanceOf(NullPointerException.class);
- }
-
- @Test
- void testMakeNullResult() {
- ValidationResult rnull = Validated.makeNullResult(MY_FIELD, TEXT);
- assertEquals(MY_FIELD, rnull.getName());
- assertThat(rnull.getResult()).contains(MY_FIELD).contains(TEXT).contains(Validated.IS_NULL);
- assertFalse(rnull.isValid());
-
- assertThatThrownBy(() -> Validated.makeNullResult(null, TEXT)).isInstanceOf(NullPointerException.class);
-
- assertThatCode(() -> Validated.makeNullResult(MY_FIELD, null)).doesNotThrowAnyException();
- }
-
- @Test
- void testValidateKeyNotNull() throws CoderException {
- BeanValidationResult result = new BeanValidationResult("", this);
- Validated.validateKeyNotNull(result, MY_FIELD, new PfConceptKey(NAME, VERSION));
- assertThat(result.getResult()).isNull();
-
- result = new BeanValidationResult("", this);
- Validated.validateKeyNotNull(result, MY_FIELD, new PfConceptKey(NAME, PfConceptKey.NULL_KEY_VERSION));
- assertThat(result.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
- 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.
- * Note: have to create the key by decoding from json, as the class will prevent
- * an invalid version from being assigned.
- */
- PfConceptKey key = new StandardCoder().decode("{'name':'myKey','version':'bogus'}".replace('\'', '"'),
- PfConceptKey.class);
- result = new BeanValidationResult("", this);
- Validated.validateKeyNotNull(result, MY_FIELD, key);
- assertThat(result.getResult()).contains(MY_FIELD, "version", "does not match regular expression");
-
- BeanValidationResult result2 = new BeanValidationResult("", this);
-
- // null parameter tests
- PfConceptKey conceptKey = new PfConceptKey();
- assertThatThrownBy(() -> Validated.validateKeyNotNull(result2, null, conceptKey))
- .isInstanceOf(NullPointerException.class);
-
- assertThatCode(() -> Validated.validateKeyNotNull(result2, MY_FIELD, null)).doesNotThrowAnyException();
- }
-
- @Test
- void testValidateKeyVersionNotNull() {
- BeanValidationResult result = new BeanValidationResult("", this);
- Validated.validateKeyVersionNotNull(result, MY_FIELD, null);
- assertThat(result.getResult()).isNull();
-
- result = new BeanValidationResult("", this);
- Validated.validateKeyVersionNotNull(result, MY_FIELD, new PfConceptKey(NAME, VERSION));
- assertThat(result.getResult()).isNull();
-
- result = new BeanValidationResult("", this);
- 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 = new BeanValidationResult("", this);
- PfConceptKey conceptKey = new PfConceptKey();
- assertThatThrownBy(() -> Validated.validateKeyVersionNotNull(result2, null, conceptKey))
- .isInstanceOf(NullPointerException.class);
-
- assertThatCode(() -> Validated.validateKeyVersionNotNull(result2, MY_FIELD, null)).doesNotThrowAnyException();
- }
-
- @Test
- void testGetKeyId() {
- // not a key field - should just use the given value
- BeanValidationResult result = new BeanValidationResult("", this);
- Validated.addResult(result, MY_FIELD, TEXT, "some message");
- assertThat(result.getResult()).contains(MY_FIELD).contains(TEXT).contains("some message");
-
- // repeat with a key field - should use the key's ID
- result = new BeanValidationResult("", this);
- Validated.addResult(result, MY_FIELD, new PfConceptKey(NAME, VERSION), "some message");
- assertThat(result.getResult()).contains(MY_FIELD).contains("myKey:1.0.0").contains("some message");
- }
-
- @AllArgsConstructor
- private static class MyString extends Validated {
- private final String text;
-
- @Override
- public BeanValidationResult validate(String fieldName) {
- if (TEXT.equals(text)) {
- return null;
- }
-
- BeanValidationResult result = new BeanValidationResult(fieldName, this);
- result.addResult(fieldName, text, ValidationStatus.INVALID, NOT_SAME);
- return result;
- }
- }
-}
--- /dev/null
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2026 OpenInfra Foundation Europe. 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base.validation.annotations;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import lombok.Getter;
+import org.junit.jupiter.api.Test;
+import org.onap.policy.common.parameters.BeanValidator;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.models.base.PfConceptKey;
+import org.onap.policy.models.base.PfKey;
+
+class VerifyKeyValidatorTest {
+ private static final String IS_A_NULL_KEY = "is a null key";
+ private static final String IS_NULL = "is null";
+ private static final String KEY_FIELD = "key";
+ private static final String STRING_VALUE = "abc";
+
+ @Test
+ void testStandardAnnotation() {
+ StdAnnotation data = new StdAnnotation();
+ data.strValue = STRING_VALUE;
+ assertThat(BeanValidator.validate("", data).getResult()).isNull();
+
+ data.strValue = null;
+ assertThat(BeanValidator.validate("", data).getResult()).contains("strValue", "null");
+ }
+
+ @Test
+ void testVerifyKey() throws CoderException {
+ FullKeyAnnot data = new FullKeyAnnot();
+
+ // null key - Jakarta validation will include all constraint violations
+ data.key = new PfConceptKey();
+ assertThat(BeanValidator.validate("", data).getResult())
+ .contains(KEY_FIELD, IS_A_NULL_KEY);
+
+ // invalid version - should invoke cascade validation
+ data.key = new StandardCoder().decode("{'name':'abc', 'version':'xyzzy'}".replace('\'', '"'),
+ PfConceptKey.class);
+ assertThat(BeanValidator.validate("", data).getResult())
+ .contains(KEY_FIELD, "version", "xyzzy", "must match");
+
+ // null name
+ data.key = new PfConceptKey(PfKey.NULL_KEY_NAME, "2.3.4");
+ assertThat(BeanValidator.validate("", data).getResult()).contains(KEY_FIELD, "name", IS_NULL);
+
+ // null version
+ data.key = new PfConceptKey(STRING_VALUE, PfKey.NULL_KEY_VERSION);
+ assertThat(BeanValidator.validate("", data).getResult()).contains(KEY_FIELD, "version", IS_NULL);
+
+ // null name, invalid version - should get two messages
+ data.key = new StandardCoder().decode("{'name':'NULL', 'version':'xyzzy'}".replace('\'', '"'),
+ PfConceptKey.class);
+ assertThat(BeanValidator.validate("", data).getResult())
+ .contains(KEY_FIELD, "name", IS_NULL, "version", "xyzzy", "must match");
+ }
+
+ @Test
+ void testEmptyKeyAnnotation() {
+ EmptyKeyAnnot data = new EmptyKeyAnnot();
+ data.key = new PfConceptKey(); // totally invalid key
+
+ // should be ok, since no validations are performed
+ assertThat(BeanValidator.validate("", data).getResult()).isNull();
+ }
+
+ @Test
+ void testVerifyKeyOnGetters() {
+ GetterKeyAnnot data = new GetterKeyAnnot();
+
+ var result = BeanValidator.validate("", data);
+ assertThat(result.getResult())
+ .contains("nullKey", IS_A_NULL_KEY)
+ .contains("nullVersionKey", "version", IS_NULL)
+ .doesNotContain("validKey");
+ }
+
+ public static class StdAnnotation {
+ @Getter
+ @NotNull
+ private String strValue;
+ }
+
+ public static class FullKeyAnnot {
+ @Getter
+ @Valid
+ @VerifyKey(keyNotNull = true, nameNotNull = true, versionNotNull = true)
+ private PfKey key;
+ }
+
+ public static class EmptyKeyAnnot {
+ @Getter
+ @Valid
+ @VerifyKey(keyNotNull = false, nameNotNull = false, versionNotNull = false)
+ private PfKey key;
+ }
+
+ public static class GetterKeyAnnot {
+ @Valid
+ @VerifyKey(versionNotNull = true)
+ public PfConceptKey getValidKey() {
+ return new PfConceptKey("validName", "1.0.0");
+ }
+
+ @Valid
+ @VerifyKey(versionNotNull = true)
+ public PfConceptKey getNullKey() {
+ return new PfConceptKey(PfKey.NULL_KEY_NAME, PfKey.NULL_KEY_VERSION);
+ }
+
+ @Valid
+ @VerifyKey(versionNotNull = true)
+ public PfConceptKey getNullVersionKey() {
+ return new PfConceptKey("validName", PfKey.NULL_KEY_VERSION);
+ }
+ }
+}