Decouple policy-models from clamp 27/142627/9
authordanielhanrahan <daniel.hanrahan@est.tech>
Tue, 2 Dec 2025 20:56:16 +0000 (20:56 +0000)
committerdanielhanrahan <daniel.hanrahan@est.tech>
Wed, 3 Dec 2025 14:39:14 +0000 (14:39 +0000)
- Copy used files from policy/models repo into clamp repo
- Copy unit tests of those files
- Update POMs to use the new internal policy-models module

Issue-ID:POLICY-5494
Change-Id: Ib1b12515d186604c4ea596dc05bed7a1830d9b70
Signed-off-by: danielhanrahan <daniel.hanrahan@est.tech>
80 files changed:
common/pom.xml
models/pom.xml
participant/participant-impl/participant-impl-policy/pom.xml
participant/participant-intermediary/pom.xml
policy-models/README.TXT [new file with mode: 0644]
policy-models/pom.xml [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/base/PfAuthorative.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/base/PfConcept.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/base/PfConceptKey.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/base/PfKey.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/base/PfKeyImpl.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/base/PfModelException.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/base/PfModelRuntimeException.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/base/PfNameVersion.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/base/PfReferenceKey.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/base/PfUtils.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/base/PfValidator.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/base/Validated.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/base/validation/annotations/PfMin.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/base/validation/annotations/VerifyKey.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/errors/concepts/ErrorResponse.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/errors/concepts/ErrorResponseInfo.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/errors/concepts/ErrorResponseUtils.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaCapabilityAssignment.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaCapabilityType.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaConceptIdentifier.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaConstraint.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaDataType.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaEntity.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaEntityComparator.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaEntityKey.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaNameVersion.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaNodeTemplate.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaNodeType.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaParameter.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicy.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyType.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaProperty.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaRelationshipType.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaRequirement.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaSchemaDefinition.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaServiceTemplate.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaServiceTemplates.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaTopologyTemplate.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaWithToscaProperties.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaWithTypeAndObjectProperties.java [new file with mode: 0644]
policy-models/src/main/java/org/onap/policy/models/tosca/utils/ToscaUtils.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/base/ExceptionsTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/base/PfConceptKeyTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/base/PfKeyImplTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/base/PfModelExceptionInfoTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/base/PfNameVersionTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/base/PfReferenceKeyTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/base/PfUtilsTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/base/PfValidatorTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/base/ValidatedTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/base/testconcepts/DummyAuthorativeConcept.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/base/testconcepts/DummyPfConcept.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/base/testconcepts/DummyPfKey.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/base/testconcepts/DummyPfNameVersion.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/errors/concepts/ErrorResponseTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/errors/concepts/ErrorResponseUtilsTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/errors/concepts/TestModels.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/PojosTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaCapabilityAssignmentTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaConceptIdentifierTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaIdentifierTestBase.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaNameVersionTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaNodeTemplateTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyTypeTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPropertyTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaRequirementTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaServiceTemplateTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaTopologyTemplateTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaWithToscaPropertiesTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaWithTypeAndObjectPropertiesTest.java [new file with mode: 0644]
policy-models/src/test/java/org/onap/policy/models/tosca/utils/ToscaUtilsTest.java [new file with mode: 0644]
pom.xml
runtime-acm/pom.xml

index c0c5b29..5fa183b 100644 (file)
@@ -36,9 +36,9 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.onap.policy.models</groupId>
-            <artifactId>policy-models-errors</artifactId>
-            <version>${policy.models.version}</version>
+            <groupId>org.onap.policy.clamp</groupId>
+            <artifactId>policy-models</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>org.onap.policy.common</groupId>
index ff278c1..0524f95 100644 (file)
     <name>${project.artifactId}</name>
 
     <dependencies>
+        <dependency>
+            <groupId>org.onap.policy.clamp</groupId>
+            <artifactId>policy-models</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.onap.policy.common</groupId>
             <artifactId>common-parameters</artifactId>
             <version>${policy.common.version}</version>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.onap.policy.models</groupId>
-            <artifactId>policy-models-errors</artifactId>
-            <version>${policy.models.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.onap.policy.models</groupId>
-            <artifactId>policy-models-base</artifactId>
-            <version>${policy.models.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.onap.policy.models</groupId>
-            <artifactId>policy-models-tosca</artifactId>
-            <version>${policy.models.version}</version>
-        </dependency>
         <dependency>
             <groupId>com.google.code.gson</groupId>
             <artifactId>gson</artifactId>
index 9beb0eb..64cb4d1 100644 (file)
@@ -34,7 +34,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.httpcomponents.core5</groupId>
-           <artifactId>httpcore5</artifactId>
+            <artifactId>httpcore5</artifactId>
         </dependency>
         <dependency>
             <groupId>org.glassfish.jersey.inject</groupId>
index 1ad363a..5b6102f 100644 (file)
             <artifactId>utils</artifactId>
             <version>${policy.common.version}</version>
         </dependency>
-        <dependency>
-            <groupId>org.onap.policy.models</groupId>
-            <artifactId>policy-models-base</artifactId>
-            <version>${policy.models.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.onap.policy.models</groupId>
-            <artifactId>policy-models-tosca</artifactId>
-            <version>${policy.models.version}</version>
-        </dependency>
         <dependency>
             <groupId>io.micrometer</groupId>
             <artifactId>micrometer-core</artifactId>
diff --git a/policy-models/README.TXT b/policy-models/README.TXT
new file mode 100644 (file)
index 0000000..08ed923
--- /dev/null
@@ -0,0 +1,8 @@
+This module contains forked code that was originally in the policy/models repo.
+
+WARNING
+In some cases, the original package structure must be maintained as Participant Intermediary library exposes these.
+In particular, the following classes/packages must NOT be modified to avoid breaking participant implementations:
+- org.onap.policy.models.base.PfModelException
+- org.onap.policy.models.base.PfModelRuntimeException
+- org.onap.policy.models.tosca.authorative.concepts.*
diff --git a/policy-models/pom.xml b/policy-models/pom.xml
new file mode 100644 (file)
index 0000000..9823bba
--- /dev/null
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ============LICENSE_START=======================================================
+  Copyright (C) 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.
+
+  SPDX-License-Identifier: Apache-2.0
+  ============LICENSE_END=========================================================
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.onap.policy.clamp</groupId>
+        <artifactId>policy-clamp</artifactId>
+        <version>9.0.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>policy-models</artifactId>
+    <name>${project.artifactId}</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onap.policy.common</groupId>
+            <artifactId>common-parameters</artifactId>
+            <version>${policy.common.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.common</groupId>
+            <artifactId>utils</artifactId>
+            <version>${policy.common.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.onap.policy.common</groupId>
+            <artifactId>utils-test</artifactId>
+            <version>${policy.common.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.re2j</groupId>
+            <artifactId>re2j</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.persistence</groupId>
+            <artifactId>jakarta.persistence-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.validation</groupId>
+            <artifactId>jakarta.validation-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.ws.rs</groupId>
+            <artifactId>jakarta.ws.rs-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-collections4</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.openpojo</groupId>
+            <artifactId>openpojo</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/policy-models/src/main/java/org/onap/policy/models/base/PfAuthorative.java b/policy-models/src/main/java/org/onap/policy/models/base/PfAuthorative.java
new file mode 100644 (file)
index 0000000..b0610e4
--- /dev/null
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+/**
+ * Interface that provides conversion to and from authorative concepts for other concepts.
+ *
+ * @author Liam Fallon (liam.fallon@est.tech)
+ *
+ * @param T the type of the authorative concept
+ */
+public interface PfAuthorative<T> {
+    /**
+     * Create an instance of the authorative concept from the other concept.
+     *
+     * @return the authorative concept
+     */
+    public T toAuthorative();
+
+    /**
+     * Set an instance of the persist concept to the equivalent values as the other concept.
+     *
+     * @param authorativeConcept the authorative concept
+     */
+    public void fromAuthorative(final T authorativeConcept);
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/base/PfConcept.java b/policy-models/src/main/java/org/onap/policy/models/base/PfConcept.java
new file mode 100644 (file)
index 0000000..c8be88d
--- /dev/null
@@ -0,0 +1,116 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019, 2023 Nordix Foundation.
+ *  Modifications Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+
+/**
+ * This class is the base class for all Policy Framework concept classes. It enforces implementation of abstract methods
+ * and interfaces on all concepts that are subclasses of this class.
+ */
+
+@NoArgsConstructor(access = AccessLevel.PROTECTED)
+public abstract class PfConcept extends Validated implements Serializable, Comparable<PfConcept> {
+    @Serial
+    private static final long serialVersionUID = -7434939557282697490L;
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    protected PfConcept(@NonNull final PfConcept copyConcept) {
+        // nothing else to do (other than @NonNull check)
+    }
+
+    /**
+     * Gets the key of this concept.
+     *
+     * @return the concept key
+     */
+    public abstract PfKey getKey();
+
+    /**
+     * Gets a list of all keys for this concept and all concepts that are defined or referenced by this concept and its
+     * sub-concepts.
+     *
+     * @return the keys used by this concept and its contained concepts
+     */
+    public abstract List<PfKey> getKeys();
+
+    /**
+     * Clean this concept, tidy up any superfluous information such as leading and trailing white space.
+     */
+    public abstract void clean();
+
+    @Override
+    public abstract boolean equals(Object otherObject);
+
+    @Override
+    public abstract String toString();
+
+    @Override
+    public abstract int hashCode();
+
+    /**
+     * Gets the ID string of this concept.
+     *
+     * @return the ID string of this concept
+     */
+    public String getId() {
+        return getKey().getId();
+    }
+
+    /**
+     * Gets the name of this concept.
+     *
+     * @return the name of this concept
+     */
+    public String getName() {
+        return getKey().getName();
+    }
+
+    /**
+     * Gets the version of this concept.
+     *
+     * @return the version of this concept
+     */
+    public String getVersion() {
+        return getKey().getVersion();
+    }
+
+    /**
+     * Checks if this key matches the given key ID.
+     *
+     * @param id the key ID to match against
+     * @return true, if this key matches the ID
+     */
+    public final boolean matchesId(@NonNull final String id) {
+        // Check the ID
+        return getId().equals(id);
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/base/PfConceptKey.java b/policy-models/src/main/java/org/onap/policy/models/base/PfConceptKey.java
new file mode 100644 (file)
index 0000000..cda2bbf
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ *  Modifications Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+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;
+
+/**
+ * A concept key uniquely identifies every first order entity in the system. Every first order concept in the system
+ * must have an {@link PfConceptKey} to identify it. Concepts that are wholly contained in another concept are
+ * identified using a {@link PfReferenceKey} key.
+ *
+ * <p>Key validation checks that the name and version fields match the NAME_REGEXP and VERSION_REGEXP
+ * regular expressions respectively.
+ */
+@Embeddable
+@Getter
+@EqualsAndHashCode(callSuper = false)
+@ToString
+public class PfConceptKey extends PfKeyImpl {
+    @Serial
+    private static final long serialVersionUID = 8932717618579392561L;
+
+    @Column(name = NAME_TOKEN, length = 120)
+    @Pattern(regexp = NAME_REGEXP)
+    private String name;
+
+    @Column(name = VERSION_TOKEN, length = 20)
+    @Pattern(regexp = VERSION_REGEXP)
+    private String version;
+
+    /**
+     * The default constructor creates a null concept key.
+     */
+    public PfConceptKey() {
+        this(NULL_KEY_NAME, NULL_KEY_VERSION);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public PfConceptKey(final PfConceptKey copyConcept) {
+        super(copyConcept);
+    }
+
+    /**
+     * Constructor to create a key with the specified name and version.
+     *
+     * @param name    the key name
+     * @param version the key version
+     */
+    public PfConceptKey(final String name, final String version) {
+        super(name, version);
+    }
+
+    /**
+     * Constructor to create a key using the key and version from the specified key ID.
+     *
+     * @param id the key ID in a format that respects the KEY_ID_REGEXP
+     */
+    public PfConceptKey(final String id) {
+        super(id);
+    }
+
+    public void setName(@NonNull final String name) {
+        this.name = Assertions.validateStringParameter(NAME_TOKEN, name, getNameRegEx());
+    }
+
+    public void setVersion(@NonNull final String version) {
+        this.version = Assertions.validateStringParameter(VERSION_TOKEN, version, getVersionRegEx());
+    }
+
+    /**
+     * Get a null concept key.
+     *
+     * @return a null concept key
+     */
+    public static PfConceptKey getNullKey() {
+        return new PfConceptKey(PfKey.NULL_KEY_NAME, PfKey.NULL_KEY_VERSION);
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/base/PfKey.java b/policy-models/src/main/java/org/onap/policy/models/base/PfKey.java
new file mode 100644 (file)
index 0000000..1ce5102
--- /dev/null
@@ -0,0 +1,140 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019, 2023 Nordix Foundation.
+ *  Modifications 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import java.io.Serial;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+
+/**
+ * The key uniquely identifies every entity in the system. This class is an abstract class to give a common parent for
+ * all key types in the system.
+ */
+@NoArgsConstructor(access = AccessLevel.PROTECTED)
+public abstract class PfKey extends PfConcept {
+    @Serial
+    private static final long serialVersionUID = 6281159885962014041L;
+
+    /** Regular expression to specify the structure of key names. */
+    public static final String NAME_REGEXP = "^[A-Za-z0-9\\-_\\.]+$";
+
+    /** Regular expression to specify the structure of key versions. */
+    public static final String VERSION_REGEXP
+        = "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)"
+        + "(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$";
+
+    /** Regular expression to specify the structure of key IDs. */
+    public static final String KEY_ID_REGEXP = "^[A-Za-z0-9\\-_\\.]+:(\\d+.){2}\\d+$";
+
+    /** Specifies the value for names in NULL keys. */
+    public static final String NULL_KEY_NAME = "NULL";
+
+    /** Specifies the value for versions in NULL keys. */
+    public static final String NULL_KEY_VERSION = "0.0.0";
+
+    /**
+     * This enumeration is returned on key compatibility checks.
+     */
+    public enum Compatibility {
+        /** The keys have different names. */
+        DIFFERENT,
+        /**
+         * The name of the key matches but the Major version number of the keys is different (x in x.y.z do not match).
+         */
+        MAJOR,
+        /**
+         * The name of the key matches but the Minor version number of the keys is different (y in x.y.z do not match).
+         */
+        MINOR,
+        /**
+         * The name of the key matches but the Patch version number of the keys is different (z in x.y.z do not match).
+         */
+        PATCH,
+        /** The keys match completely. */
+        IDENTICAL
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    protected PfKey(final PfKey copyConcept) {
+        super(copyConcept);
+    }
+
+    @Override
+    public abstract String getId();
+
+    /**
+     * Return the result of a compatibility check of two keys.
+     *
+     * @param otherKey the key to check compatibility against
+     * @return the compatibility result of the check
+     */
+    public abstract Compatibility getCompatibility(@NonNull PfKey otherKey);
+
+    /**
+     * Check if two keys are compatible, that is the keys are IDENTICAL or have only MINOR, PATCH differences.
+     *
+     * @param otherKey the key to check compatibility against
+     * @return true, if the keys are compatible
+     */
+    public abstract boolean isCompatible(@NonNull PfKey otherKey);
+
+    /**
+     * Check if this key is a newer version than the other key.
+     *
+     * @param otherKey the key to check against
+     * @return true, if this key is newer than the other key
+     */
+    public abstract boolean isNewerThan(@NonNull PfKey otherKey);
+
+    /**
+     * Check if a key equals its null key.
+     *
+     * @return true, if the key is a null key
+     */
+    public abstract boolean isNullKey();
+
+    /**
+     * Get the major version of a key.
+     *
+     * @return the major version of a key
+     */
+    public abstract int getMajorVersion();
+
+    /**
+     * Get the minor version of a key.
+     *
+     * @return the minor version of a key
+     */
+    public abstract int getMinorVersion();
+
+    /**
+     * Get the patch version of a key.
+     *
+     * @return the patch version of a key
+     */
+    public abstract int getPatchVersion();
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/base/PfKeyImpl.java b/policy-models/src/main/java/org/onap/policy/models/base/PfKeyImpl.java
new file mode 100644 (file)
index 0000000..105e6f7
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019-2020, 2023 Nordix Foundation.
+ *  Modifications Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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;
+
+import java.io.Serial;
+import java.util.ArrayList;
+import java.util.List;
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.ToString;
+import org.onap.policy.common.utils.validation.Assertions;
+
+/**
+ * A key, upon which other key subclasses can be built, providing implementations of the methods.
+ */
+@Getter
+@ToString
+public abstract class PfKeyImpl extends PfKey {
+    @Serial
+    private static final long serialVersionUID = 8932717618579392561L;
+
+    public static final String NAME_TOKEN = "name";
+    public static final String VERSION_TOKEN = "version";
+
+    /**
+     * The default constructor creates a null concept key.
+     */
+    protected PfKeyImpl() {
+        this(NULL_KEY_NAME, NULL_KEY_VERSION);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    protected PfKeyImpl(final PfKeyImpl copyConcept) {
+        super(copyConcept);
+        setName(copyConcept.getName());
+        setVersion(copyConcept.getVersion());
+    }
+
+    /**
+     * Constructor to create a key with the specified name and version.
+     *
+     * @param name the key name
+     * @param version the key version
+     */
+    protected PfKeyImpl(@NonNull final String name, @NonNull final String version) {
+        super();
+        setName(name);
+        setVersion(version);
+    }
+
+    /**
+     * Constructor to create a key using the key and version from the specified key ID.
+     *
+     * @param id the key ID in a format that respects the KEY_ID_REGEXP
+     */
+    protected PfKeyImpl(@NonNull final String id) {
+        // Check the incoming ID is valid
+        Assertions.validateStringParameter("id", id, getKeyIdRegEx());
+
+        // Split on colon, if the id passes the regular expression test above
+        // it'll have just one colon separating the name and version
+        // No need for range checks or size checks on the array
+        final String[] nameVersionArray = id.split(":");
+
+        // Return the new key
+        setName(nameVersionArray[0]);
+        setVersion(nameVersionArray[1]);
+    }
+
+    public abstract void setName(@NonNull final String name);
+
+    public abstract void setVersion(@NonNull final String version);
+
+    @Override
+    public PfKeyImpl getKey() {
+        return this;
+    }
+
+    @Override
+    public List<PfKey> getKeys() {
+        final List<PfKey> keyList = new ArrayList<>();
+        keyList.add(getKey());
+        return keyList;
+    }
+
+    @Override
+    public String getId() {
+        return getName() + ':' + getVersion();
+    }
+
+    @Override
+    public boolean isNullKey() {
+        return (PfKey.NULL_KEY_NAME.equals(getName()) && PfKey.NULL_KEY_VERSION.equals(getVersion()));
+    }
+
+    /**
+     * Determines if the name is "null".
+     *
+     * @return {@code true} if the name is null, {@code false} otherwise
+     */
+    public boolean isNullName() {
+        return PfKey.NULL_KEY_NAME.equals(getName());
+    }
+
+    /**
+     * Determines if the version is "null".
+     *
+     * @return {@code true} if the version is null, {@code false} otherwise
+     */
+    public boolean isNullVersion() {
+        return PfKey.NULL_KEY_VERSION.equals(getVersion());
+    }
+
+    @Override
+    public PfKey.Compatibility getCompatibility(@NonNull final PfKey otherKey) {
+        if (!(otherKey instanceof PfKeyImpl otherConceptKey)) {
+            return Compatibility.DIFFERENT;
+        }
+
+        if (this.equals(otherConceptKey)) {
+            return Compatibility.IDENTICAL;
+        }
+        if (!this.getName().equals(otherConceptKey.getName())) {
+            return Compatibility.DIFFERENT;
+        }
+
+        final String[] thisVersionArray = getVersion().split("\\.");
+        final String[] otherVersionArray = otherConceptKey.getVersion().split("\\.");
+
+        // There must always be at least one element in each version
+        if (!thisVersionArray[0].equals(otherVersionArray[0])) {
+            return Compatibility.MAJOR;
+        }
+
+        if (thisVersionArray.length >= 2 && otherVersionArray.length >= 2
+            && !thisVersionArray[1].equals(otherVersionArray[1])) {
+            return Compatibility.MINOR;
+        }
+
+        return Compatibility.PATCH;
+    }
+
+    @Override
+    public boolean isCompatible(@NonNull final PfKey otherKey) {
+        if (!(otherKey instanceof PfKeyImpl otherConceptKey)) {
+            return false;
+        }
+
+        final var compatibility = this.getCompatibility(otherConceptKey);
+
+        return !(compatibility == Compatibility.DIFFERENT || compatibility == Compatibility.MAJOR);
+    }
+
+    @Override
+    public boolean isNewerThan(@NonNull final PfKey otherKey) {
+        Assertions.instanceOf(otherKey, PfKeyImpl.class);
+
+        final PfKeyImpl otherConceptKey = (PfKeyImpl) otherKey;
+
+        if (this.equals(otherConceptKey)) {
+            return false;
+        }
+
+        if (!this.getName().equals(otherConceptKey.getName())) {
+            return this.getName().compareTo(otherConceptKey.getName()) > 0;
+        }
+
+        final String[] thisVersionArray = getVersion().split("\\.");
+        final String[] otherVersionArray = otherConceptKey.getVersion().split("\\.");
+
+        // There must always be at least one element in each version
+        if (!thisVersionArray[0].equals(otherVersionArray[0])) {
+            return Integer.parseInt(thisVersionArray[0]) > Integer.parseInt(otherVersionArray[0]);
+        }
+
+        if (thisVersionArray.length >= 2 && otherVersionArray.length >= 2
+            && !thisVersionArray[1].equals(otherVersionArray[1])) {
+            return Integer.parseInt(thisVersionArray[1]) > Integer.parseInt(otherVersionArray[1]);
+        }
+
+        if (thisVersionArray.length >= 3 && otherVersionArray.length >= 3
+            && !thisVersionArray[2].equals(otherVersionArray[2])) {
+            return Integer.parseInt(thisVersionArray[2]) > Integer.parseInt(otherVersionArray[2]);
+        }
+
+        return false;
+    }
+
+    @Override
+    public int getMajorVersion() {
+        final String[] versionArray = getVersion().split("\\.");
+
+        // There must always be at least one element in each version
+        return Integer.parseInt(versionArray[0]);
+    }
+
+    @Override
+    public int getMinorVersion() {
+        final String[] versionArray = getVersion().split("\\.");
+
+        if (versionArray.length >= 2) {
+            return Integer.parseInt(versionArray[1]);
+        } else {
+            return 0;
+        }
+    }
+
+    @Override
+    public int getPatchVersion() {
+        final String[] versionArray = getVersion().split("\\.");
+
+        if (versionArray.length >= 3) {
+            return Integer.parseInt(versionArray[2]);
+        } else {
+            return 0;
+        }
+    }
+
+    @Override
+    public void clean() {
+        setName(getName());
+        setVersion(getVersion());
+    }
+
+    @Override
+    public int compareTo(@NonNull final PfConcept otherObj) {
+        Assertions.argumentNotNull(otherObj, "comparison object may not be null");
+
+        if (this == otherObj) {
+            return 0;
+        }
+        if (getClass() != otherObj.getClass()) {
+            return getClass().getName().compareTo(otherObj.getClass().getName());
+        }
+
+        final PfKeyImpl other = (PfKeyImpl) otherObj;
+
+        if (!getName().equals(other.getName())) {
+            return getName().compareTo(other.getName());
+        }
+        return getVersion().compareTo(other.getVersion());
+    }
+
+    /**
+     * Gets the regular expression used to validate a name.
+     *
+     * @return the regular expression used to validate a name
+     */
+    protected String getNameRegEx() {
+        return NAME_REGEXP;
+    }
+
+    /**
+     * Gets the regular expression used to validate a version.
+     *
+     * @return the regular expression used to validate a version
+     */
+    protected String getVersionRegEx() {
+        return VERSION_REGEXP;
+    }
+
+    /**
+     * Gets the regular expression used to validate a key id.
+     *
+     * @return the regular expression used to validate a key id
+     */
+    protected String getKeyIdRegEx() {
+        return KEY_ID_REGEXP;
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/base/PfModelException.java b/policy-models/src/main/java/org/onap/policy/models/base/PfModelException.java
new file mode 100644 (file)
index 0000000..9ffac08
--- /dev/null
@@ -0,0 +1,96 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019, 2023 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import jakarta.ws.rs.core.Response;
+import java.io.Serial;
+import lombok.Getter;
+import lombok.ToString;
+import org.onap.policy.models.errors.concepts.ErrorResponse;
+import org.onap.policy.models.errors.concepts.ErrorResponseInfo;
+import org.onap.policy.models.errors.concepts.ErrorResponseUtils;
+
+/**
+ * This class is a base exception from which all model exceptions are subclasses.
+ */
+@Getter
+@ToString
+public class PfModelException extends Exception implements ErrorResponseInfo {
+    @Serial
+    private static final long serialVersionUID = -8507246953751956974L;
+
+    // The error response of the exception
+    private final ErrorResponse errorResponse = new ErrorResponse();
+
+    // The object on which the exception was thrown
+    private final transient Object object;
+
+    /**
+     * Instantiates a new model exception.
+     *
+     * @param statusCode the return code for the exception
+     * @param message    the message on the exception
+     */
+    public PfModelException(final Response.Status statusCode, final String message) {
+        this(statusCode, message, null);
+    }
+
+    /**
+     * Instantiates a new model exception.
+     *
+     * @param statusCode the return code for the exception
+     * @param message    the message on the exception
+     * @param object     the object that the exception was thrown on
+     */
+    public PfModelException(final Response.Status statusCode, final String message, final Object object) {
+        super(message);
+        errorResponse.setResponseCode(statusCode);
+        ErrorResponseUtils.getExceptionMessages(errorResponse, this);
+        this.object = object;
+    }
+
+    /**
+     * Instantiates a new model exception.
+     *
+     * @param statusCode the return code for the exception
+     * @param message    the message on the exception
+     * @param exception  the exception that caused this exception
+     */
+    public PfModelException(final Response.Status statusCode, final String message, final Exception exception) {
+        this(statusCode, message, exception, null);
+    }
+
+    /**
+     * Instantiates a new exception.
+     *
+     * @param statusCode the return code for the exception
+     * @param message    the message on the exception
+     * @param exception  the exception that caused this exception
+     * @param object     the object that the exception was thrown on
+     */
+    public PfModelException(final Response.Status statusCode, final String message, final Exception exception,
+                            final Object object) {
+        super(message, exception);
+        errorResponse.setResponseCode(statusCode);
+        ErrorResponseUtils.getExceptionMessages(errorResponse, this);
+        this.object = object;
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/base/PfModelRuntimeException.java b/policy-models/src/main/java/org/onap/policy/models/base/PfModelRuntimeException.java
new file mode 100644 (file)
index 0000000..44e9db9
--- /dev/null
@@ -0,0 +1,108 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019, 2021, 2023 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import jakarta.ws.rs.core.Response;
+import java.io.Serial;
+import lombok.Getter;
+import lombok.ToString;
+import org.onap.policy.models.errors.concepts.ErrorResponse;
+import org.onap.policy.models.errors.concepts.ErrorResponseInfo;
+import org.onap.policy.models.errors.concepts.ErrorResponseUtils;
+
+/**
+ * This class is a base model run time exception from which all model run time exceptions are subclasses.
+ */
+@Getter
+@ToString
+public class PfModelRuntimeException extends RuntimeException implements ErrorResponseInfo {
+    @Serial
+    private static final long serialVersionUID = -8507246953751956974L;
+
+    // The error response of the exception
+    private final ErrorResponse errorResponse = new ErrorResponse();
+
+    // The object on which the exception was thrown
+    private final transient Object object;
+
+    /**
+     * Instantiates a new model runtime exception.
+     *
+     * @param statusCode the return code for the exception
+     * @param message    the message on the exception
+     */
+    public PfModelRuntimeException(final Response.Status statusCode, final String message) {
+        this(statusCode, message, null);
+    }
+
+    /**
+     * Instantiates a new model runtime exception.
+     *
+     * @param statusCode the return code for the exception
+     * @param message    the message on the exception
+     * @param object     the object that the exception was thrown on
+     */
+    public PfModelRuntimeException(final Response.Status statusCode, final String message, final Object object) {
+        super(message);
+        this.object = object;
+        errorResponse.setResponseCode(statusCode);
+        ErrorResponseUtils.getExceptionMessages(errorResponse, this);
+    }
+
+    /**
+     * Instantiates a new model runtime exception.
+     *
+     * @param statusCode the return code for the exception
+     * @param message    the message on the exception
+     * @param exception  the exception that caused this model exception
+     */
+    public PfModelRuntimeException(final Response.Status statusCode, final String message, final Exception exception) {
+        this(statusCode, message, exception, null);
+    }
+
+    /**
+     * Instantiates a new model runtime exception from a PfModelException instance.
+     *
+     * @param exception the exception that caused this model exception
+     */
+    public PfModelRuntimeException(final PfModelException exception) {
+        super(exception.getMessage(), exception);
+        this.object = exception.getObject();
+        errorResponse.setResponseCode(exception.getErrorResponse().getResponseCode());
+        ErrorResponseUtils.getExceptionMessages(errorResponse, this);
+    }
+
+    /**
+     * Instantiates a new model runtime exception.
+     *
+     * @param statusCode the return code for the exception
+     * @param message    the message on the exception
+     * @param exception  the exception that caused this model exception
+     * @param object     the object that the exception was thrown on
+     */
+    public PfModelRuntimeException(final Response.Status statusCode, final String message, final Exception exception,
+                                   final Object object) {
+        super(message, exception);
+        this.object = object;
+        errorResponse.setResponseCode(statusCode);
+        ErrorResponseUtils.getExceptionMessages(errorResponse, this);
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/base/PfNameVersion.java b/policy-models/src/main/java/org/onap/policy/models/base/PfNameVersion.java
new file mode 100644 (file)
index 0000000..4e41770
--- /dev/null
@@ -0,0 +1,96 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019-2020 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import org.apache.commons.lang3.ObjectUtils;
+import org.onap.policy.common.utils.validation.Version;
+
+/**
+ * An interface that forces a POJO to have getName() and getVersion() methods.
+ *
+ * @author Liam Fallon (liam.fallon@est.tech)
+ */
+public interface PfNameVersion {
+    public String getName();
+
+    public void setName(final String name);
+
+    public String getVersion();
+
+    public void setVersion(final String version);
+
+    /**
+     * Get the defined name for a concept, return null if no name is defined.
+     *
+     * @return the defined name
+     */
+    public default String getDefinedName() {
+        return getName();
+    }
+
+    /**
+     * Get the defined version for a concept, return null if no version is defined.
+     *
+     * @return the defined version
+     */
+    public default String getDefinedVersion() {
+        return getVersion();
+    }
+
+    /**
+     * Compare two name version implementation objects.
+     *
+     * @param left the left name/version implementation
+     * @param right the right name/version implementation
+     * @return the comparison resilt
+     */
+    public default int compareNameVersion(final PfNameVersion left, final PfNameVersion right) {
+        if (left == null && right == null) {
+            return 0;
+        }
+
+        if (left == null) {
+            return 1;
+        }
+
+        if (right == null) {
+            return -1;
+        }
+
+        int result = ObjectUtils.compare(left.getName(), right.getName());
+        if (result != 0) {
+            return result;
+        }
+
+        if (left.getVersion() == null && right.getVersion() == null) {
+            return 0;
+        }
+
+        if (left.getVersion() == null) {
+            return 1;
+        }
+
+        if (right.getVersion() == null) {
+            return -1;
+        }
+        return new Version(left.getVersion()).compareTo(new Version(right.getVersion()));
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/base/PfReferenceKey.java b/policy-models/src/main/java/org/onap/policy/models/base/PfReferenceKey.java
new file mode 100644 (file)
index 0000000..246f8f0
--- /dev/null
@@ -0,0 +1,368 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019, 2021, 2023 Nordix Foundation.
+ *  Modifications Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import java.io.Serial;
+import java.util.ArrayList;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NonNull;
+import org.onap.policy.common.parameters.annotations.NotNull;
+import org.onap.policy.common.parameters.annotations.Pattern;
+import org.onap.policy.common.utils.validation.Assertions;
+
+/**
+ * A reference key identifies entities in the system that are contained in other entities. Every contained concept in
+ * the system must have an {@link PfReferenceKey} to identify it. Non-contained first order concepts are identified
+ * using an {@link PfConceptKey} key.
+ *
+ * <p>An {@link PfReferenceKey} contains an {@link PfConceptKey} key reference to the first order entity that contains
+ * it. The local name of the reference key must uniquely identify the referenced concept among those concepts contained
+ * in the reference key's parent. In other words, if a parent concept has more than one child, the local name in the key
+ * of all its children must be unique.
+ *
+ * <p>If a reference key's parent is itself a reference key, then the parent's local name must be set in the reference
+ * key. If the parent is a first order concept, then the parent's local name in the key will be set to NULL.
+ *
+ * <p>Key validation checks that the parent name and parent version fields match the NAME_REGEXP and
+ * VERSION_REGEXP regular expressions respectively and that the local name fields match the
+ * LOCAL_NAME_REGEXP regular expression.
+ */
+@Embeddable
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class PfReferenceKey extends PfKey {
+    private static final String PARENT_KEY_NAME = "parentKeyName";
+    private static final String PARENT_KEY_VERSION = "parentKeyVersion";
+    private static final String PARENT_LOCAL_NAME = "parentLocalName";
+    private static final String LOCAL_NAME = "localName";
+
+    @Serial
+    private static final long serialVersionUID = 8932717618579392561L;
+
+    /**
+     * Regular expression to specify the structure of local names in reference keys.
+     */
+    public static final String LOCAL_NAME_REGEXP = "[A-Za-z0-9\\-_\\.]+|^$";
+
+    /**
+     * Regular expression to specify the structure of IDs in reference keys.
+     */
+    public static final String REFERENCE_KEY_ID_REGEXP =
+        "[A-Za-z0-9\\-_]+:[0-9].[0-9].[0-9]:[A-Za-z0-9\\-_]+:[A-Za-z0-9\\-_]+";
+
+    private static final int PARENT_NAME_FIELD = 0;
+    private static final int PARENT_VERSION_FIELD = 1;
+    private static final int PARENT_LOCAL_NAME_FIELD = 2;
+    private static final int LOCAL_NAME_FIELD = 3;
+
+    @Column(name = PARENT_KEY_NAME, length = 120)
+    @NotNull
+    @Pattern(regexp = NAME_REGEXP)
+    private String parentKeyName;
+
+    @Column(name = PARENT_KEY_VERSION, length = 15)
+    @NotNull
+    @Pattern(regexp = VERSION_REGEXP)
+    private String parentKeyVersion;
+
+    @Column(name = PARENT_LOCAL_NAME, length = 120)
+    @NotNull
+    @Pattern(regexp = LOCAL_NAME_REGEXP)
+    private String parentLocalName;
+
+    @Column(name = LOCAL_NAME, length = 120)
+    @NotNull
+    @Pattern(regexp = LOCAL_NAME_REGEXP)
+    private String localName;
+
+    /**
+     * The default constructor creates a null reference key.
+     */
+    public PfReferenceKey() {
+        this(NULL_KEY_NAME, NULL_KEY_VERSION, NULL_KEY_NAME, NULL_KEY_NAME);
+    }
+
+    /**
+     * The Copy Constructor creates a key by copying another key.
+     *
+     * @param referenceKey the reference key to copy from
+     */
+    public PfReferenceKey(final PfReferenceKey referenceKey) {
+        this(referenceKey.getParentKeyName(), referenceKey.getParentKeyVersion(), referenceKey.getParentLocalName(),
+            referenceKey.getLocalName());
+    }
+
+    /**
+     * Constructor to create a null reference key for the specified parent concept key.
+     *
+     * @param pfConceptKey the parent concept key of this reference key
+     */
+    public PfReferenceKey(final PfConceptKey pfConceptKey) {
+        this(pfConceptKey.getName(), pfConceptKey.getVersion(), NULL_KEY_NAME, NULL_KEY_NAME);
+    }
+
+    /**
+     * Constructor to create a reference key for the given parent concept key with the given local name.
+     *
+     * @param pfConceptKey the parent concept key of this reference key
+     * @param localName    the local name of this reference key
+     */
+    public PfReferenceKey(final PfConceptKey pfConceptKey, final String localName) {
+        this(pfConceptKey, NULL_KEY_NAME, localName);
+    }
+
+    /**
+     * Constructor to create a reference key for the given parent reference key with the given local name.
+     *
+     * @param parentReferenceKey the parent reference key of this reference key
+     * @param localName          the local name of this reference key
+     */
+    public PfReferenceKey(final PfReferenceKey parentReferenceKey, final String localName) {
+        this(parentReferenceKey.getParentConceptKey(), parentReferenceKey.getLocalName(), localName);
+    }
+
+    /**
+     * Constructor to create a reference key for the given parent reference key (specified by the parent reference key's
+     * concept key and local name) with the given local name.
+     *
+     * @param pfConceptKey    the concept key of the parent reference key of this reference key
+     * @param parentLocalName the local name of the parent reference key of this reference key
+     * @param localName       the local name of this reference key
+     */
+    public PfReferenceKey(final PfConceptKey pfConceptKey, final String parentLocalName, final String localName) {
+        this(pfConceptKey.getName(), pfConceptKey.getVersion(), parentLocalName, localName);
+    }
+
+    /**
+     * Constructor to create a reference key for the given parent concept key (specified by the parent concept key's
+     * name and version) with the given local name.
+     *
+     * @param parentKeyName    the name of the parent concept key of this reference key
+     * @param parentKeyVersion the version of the parent concept key of this reference key
+     * @param localName        the local name of this reference key
+     */
+    public PfReferenceKey(final String parentKeyName, final String parentKeyVersion, final String localName) {
+        this(parentKeyName, parentKeyVersion, NULL_KEY_NAME, localName);
+    }
+
+    /**
+     * Constructor to create a reference key for the given parent key (specified by the parent key's name, version nad
+     * local name) with the given local name.
+     *
+     * @param parentKeyName    the parent key name of this reference key
+     * @param parentKeyVersion the parent key version of this reference key
+     * @param parentLocalName  the parent local name of this reference key
+     * @param localName        the local name of this reference key
+     */
+    public PfReferenceKey(final String parentKeyName, final String parentKeyVersion, final String parentLocalName,
+                          final String localName) {
+        super();
+        this.parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, parentKeyName, NAME_REGEXP);
+        this.parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION, parentKeyVersion,
+            VERSION_REGEXP);
+        this.parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME, parentLocalName,
+            LOCAL_NAME_REGEXP);
+        this.localName = Assertions.validateStringParameter(LOCAL_NAME, localName, LOCAL_NAME_REGEXP);
+    }
+
+    /**
+     * Constructor to create a key from the specified key ID.
+     *
+     * @param id the key ID in a format that respects the KEY_ID_REGEXP
+     */
+    public PfReferenceKey(final String id) {
+        final var conditionedId = Assertions.validateStringParameter("id", id, REFERENCE_KEY_ID_REGEXP);
+
+        // Split on colon, if the id passes the regular expression test above
+        // it'll have just three colons separating the parent name,
+        // parent version, parent local name, and and local name
+        // No need for range checks or size checks on the array
+        final String[] nameVersionNameArray = conditionedId.split(":");
+
+        // Initiate the new key
+        parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, nameVersionNameArray[PARENT_NAME_FIELD],
+            NAME_REGEXP);
+        parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION,
+            nameVersionNameArray[PARENT_VERSION_FIELD], VERSION_REGEXP);
+        parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME,
+            nameVersionNameArray[PARENT_LOCAL_NAME_FIELD], LOCAL_NAME_REGEXP);
+        localName = Assertions.validateStringParameter(LOCAL_NAME, nameVersionNameArray[LOCAL_NAME_FIELD],
+            LOCAL_NAME_REGEXP);
+    }
+
+    /**
+     * Get a null reference key.
+     *
+     * @return a null reference key
+     */
+    public static PfReferenceKey getNullKey() {
+        return new PfReferenceKey(PfKey.NULL_KEY_NAME, PfKey.NULL_KEY_VERSION, PfKey.NULL_KEY_NAME,
+            PfKey.NULL_KEY_NAME);
+    }
+
+    @Override
+    public PfReferenceKey getKey() {
+        return this;
+    }
+
+    @Override
+    public List<PfKey> getKeys() {
+        final List<PfKey> keyList = new ArrayList<>();
+        keyList.add(getKey());
+        return keyList;
+    }
+
+    @Override
+    public String getId() {
+        return parentKeyName + ':' + parentKeyVersion + ':' + parentLocalName + ':' + localName;
+    }
+
+    @Override
+    public boolean isNullKey() {
+        return (PfKey.NULL_KEY_NAME.equals(this.getParentKeyName()) && PfKey.NULL_KEY_VERSION
+            .equals(this.getParentKeyVersion()) && PfKey.NULL_KEY_NAME.equals(this.getParentLocalName())
+            && PfKey.NULL_KEY_NAME.equals(this.getLocalName()));
+    }
+
+    /**
+     * Gets the parent concept key of this reference key.
+     *
+     * @return the parent concept key of this reference key
+     */
+    public PfConceptKey getParentConceptKey() {
+        return new PfConceptKey(parentKeyName, parentKeyVersion);
+    }
+
+    /**
+     * Gets the parent reference key of this reference key.
+     *
+     * @return the parent reference key of this reference key
+     */
+    public PfReferenceKey getParentReferenceKey() {
+        return new PfReferenceKey(parentKeyName, parentKeyVersion, parentLocalName);
+    }
+
+    /**
+     * Sets the parent concept key of this reference key.
+     *
+     * @param parentKey the parent concept key of this reference key
+     */
+    public void setParentConceptKey(final PfConceptKey parentKey) {
+        Assertions.argumentNotNull(parentKey, "parentKey may not be null");
+
+        parentKeyName = parentKey.getName();
+        parentKeyVersion = parentKey.getVersion();
+        parentLocalName = NULL_KEY_NAME;
+    }
+
+    /**
+     * Sets the parent reference key of this reference key.
+     *
+     * @param parentKey the parent reference key of this reference key
+     */
+    public void setParentReferenceKey(final PfReferenceKey parentKey) {
+        Assertions.argumentNotNull(parentKey, "parentKey may not be null");
+
+        parentKeyName = parentKey.getParentKeyName();
+        parentKeyVersion = parentKey.getParentKeyVersion();
+        parentLocalName = parentKey.getLocalName();
+    }
+
+    @Override
+    public PfKey.Compatibility getCompatibility(@NonNull final PfKey otherKey) {
+        if (!(otherKey instanceof PfReferenceKey otherReferenceKey)) {
+            return Compatibility.DIFFERENT;
+        }
+
+        return this.getParentConceptKey().getCompatibility(otherReferenceKey.getParentConceptKey());
+    }
+
+    @Override
+    public boolean isCompatible(@NonNull final PfKey otherKey) {
+        if (!(otherKey instanceof PfReferenceKey otherReferenceKey)) {
+            return false;
+        }
+
+        return this.getParentConceptKey().isCompatible(otherReferenceKey.getParentConceptKey());
+    }
+
+    @Override
+    public int getMajorVersion() {
+        return this.getParentConceptKey().getMajorVersion();
+    }
+
+    @Override
+    public int getMinorVersion() {
+        return this.getParentConceptKey().getMinorVersion();
+    }
+
+    @Override
+    public int getPatchVersion() {
+        return this.getParentConceptKey().getPatchVersion();
+    }
+
+
+    @Override
+    public boolean isNewerThan(@NonNull final PfKey otherKey) {
+        Assertions.instanceOf(otherKey, PfReferenceKey.class);
+
+        final PfReferenceKey otherReferenceKey = (PfReferenceKey) otherKey;
+
+        return this.getParentConceptKey().isNewerThan(otherReferenceKey.getParentConceptKey());
+    }
+
+    @Override
+    public void clean() {
+        parentKeyName = Assertions.validateStringParameter(PARENT_KEY_NAME, parentKeyName, NAME_REGEXP);
+        parentKeyVersion = Assertions.validateStringParameter(PARENT_KEY_VERSION, parentKeyVersion, VERSION_REGEXP);
+        parentLocalName = Assertions.validateStringParameter(PARENT_LOCAL_NAME, parentLocalName, LOCAL_NAME_REGEXP);
+        localName = Assertions.validateStringParameter(LOCAL_NAME, localName, LOCAL_NAME_REGEXP);
+    }
+
+    @Override
+    public int compareTo(@NonNull final PfConcept otherObj) {
+        Assertions.argumentNotNull(otherObj, "comparison object may not be null");
+
+        if (this == otherObj) {
+            return 0;
+        }
+        if (getClass() != otherObj.getClass()) {
+            return getClass().getName().compareTo(otherObj.getClass().getName());
+        }
+
+        final PfReferenceKey other = (PfReferenceKey) otherObj;
+        if (!parentKeyName.equals(other.parentKeyName)) {
+            return parentKeyName.compareTo(other.parentKeyName);
+        }
+        if (!parentKeyVersion.equals(other.parentKeyVersion)) {
+            return parentKeyVersion.compareTo(other.parentKeyVersion);
+        }
+        if (!parentLocalName.equals(other.parentLocalName)) {
+            return parentLocalName.compareTo(other.parentLocalName);
+        }
+        return localName.compareTo(other.localName);
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/base/PfUtils.java b/policy-models/src/main/java/org/onap/policy/models/base/PfUtils.java
new file mode 100644 (file)
index 0000000..f7e6b5a
--- /dev/null
@@ -0,0 +1,188 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019-2021, 2023-2024 Nordix Foundation.
+ *  Modifications Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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;
+
+import jakarta.ws.rs.core.Response;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
+
+/**
+ * Utility class for Policy Framework concept utilities.
+ *
+ * @author Liam Fallon (liam.fallon@est.tech)
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class PfUtils {
+
+    /**
+     * Compare two objects using their equals methods, nulls are allowed.
+     *
+     * @param leftObject  the first object
+     * @param rightObject the second object
+     * @return a measure of the comparison
+     */
+    public static int compareObjects(final Object leftObject, final Object rightObject) {
+        if (leftObject == null && rightObject == null) {
+            return 0;
+        }
+
+        if (leftObject == null) {
+            return 1;
+        }
+
+        if (rightObject == null) {
+            return -1;
+        }
+
+        if (!leftObject.equals(rightObject)) {
+            return leftObject.hashCode() - rightObject.hashCode();
+        }
+
+        return 0;
+    }
+
+    /**
+     * Compare two collections of the same type, nulls are allowed.
+     *
+     * @param leftCollection  the first collection
+     * @param rightCollection the second collection
+     * @return a measure of the comparison
+     */
+    public static <T> int compareCollections(final Collection<T> leftCollection, final Collection<T> rightCollection) {
+        if (CollectionUtils.isEmpty(leftCollection) && CollectionUtils.isEmpty(rightCollection)) {
+            return 0;
+        }
+
+        return compareObjects(leftCollection, rightCollection);
+    }
+
+
+    /**
+     * Compare two maps of the same type, nulls are allowed.
+     *
+     * @param leftMap  the first map
+     * @param rightMap the second map
+     * @return a measure of the comparison
+     */
+    public static <K, V> int compareMaps(final Map<K, V> leftMap, final Map<K, V> rightMap) {
+        if (MapUtils.isEmpty(leftMap) && MapUtils.isEmpty(rightMap)) {
+            return 0;
+        }
+
+        return compareObjects(leftMap, rightMap);
+    }
+
+    /**
+     * Convenience method to apply a mapping function to all the elements of a list, generating a new list.
+     *
+     * @param source       list whose elements are to be mapped, or {@code null}
+     * @param mapFunc      mapping function
+     * @param defaultValue value to be returned if source is {@code null}
+     * @return a new list, containing mappings of all the items in the original list
+     */
+    public static <T, R> List<R> mapList(List<T> source, Function<T, R> mapFunc, List<R> defaultValue) {
+        if (source == null) {
+            return defaultValue;
+        }
+
+        return source.stream().map(mapFunc).collect(Collectors.toList()); //NOSONAR
+    }
+
+    /**
+     * Convenience method to apply a mapping function to all the elements of a list, generating a new list.
+     *
+     * @param source  list whose elements are to be mapped, or {@code null}
+     * @param mapFunc mapping function
+     * @return a new list, containing mappings of all the items in the original list, or {@code null} if the source
+     *      is {@code null}
+     */
+    public static <T, R> List<R> mapList(List<T> source, Function<T, R> mapFunc) {
+        return mapList(source, mapFunc, null);
+    }
+
+    /**
+     * Convenience method to apply a mapping function to all the values of a map, generating a new map.
+     *
+     * @param source       map whose values are to be mapped, or {@code null}
+     * @param mapFunc      mapping function
+     * @param defaultValue value to be returned if source is {@code null}
+     * @return a new map, containing mappings of all the items in the original map
+     */
+    public static <K, T, R> Map<K, R> mapMap(Map<K, T> source, Function<T, R> mapFunc, Map<K, R> defaultValue) {
+        if (source == null) {
+            return defaultValue;
+        }
+
+        Map<K, R> map = new LinkedHashMap<>();
+        for (Entry<K, T> ent : source.entrySet()) {
+            map.put(ent.getKey(), mapFunc.apply(ent.getValue()));
+        }
+
+        return map;
+    }
+
+    /**
+     * Convenience method to apply a mapping function to all the values of a map, generating a new map.
+     *
+     * @param source  map whose values are to be mapped, or {@code null}
+     * @param mapFunc mapping function
+     * @return a new map, containing mappings of all the items in the original map, or {@code null} if the source is
+     *      {@code null}
+     */
+    public static <K, T, R> Map<K, R> mapMap(Map<K, T> source, Function<T, R> mapFunc) {
+        return mapMap(source, mapFunc, null);
+    }
+
+    /**
+     * Makes a copy of an object using the copy constructor from the object's class.
+     *
+     * @param source object to be copied
+     * @return a copy of the source, or {@code null} if the source is {@code null}
+     * @throws PfModelRuntimeException if the object cannot be copied
+     */
+    public static <T> T makeCopy(T source) {
+        if (source == null) {
+            return null;
+        }
+
+        try {
+            @SuppressWarnings("unchecked") Class<? extends T> clazz = (Class<? extends T>) source.getClass();
+
+            return clazz.getConstructor(clazz).newInstance(source);
+
+        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException
+                 | RuntimeException e) {
+            throw new PfModelRuntimeException(Response.Status.INTERNAL_SERVER_ERROR,
+                "error copying concept key class: " + source.getClass().getName(), e);
+        }
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/base/PfValidator.java b/policy-models/src/main/java/org/onap/policy/models/base/PfValidator.java
new file mode 100644 (file)
index 0000000..e9c8591
--- /dev/null
@@ -0,0 +1,134 @@
+/*-
+ * ============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.PfMin;
+import org.onap.policy.models.base.validation.annotations.VerifyKey;
+
+public class PfValidator extends BeanValidator {
+
+    @Override
+    protected void addValidators(ValueValidator validator) {
+        super.addValidators(validator);
+
+        validator.addAnnotation(VerifyKey.class, this::verKey);
+        validator.addAnnotation(PfMin.class, this::verPfMin);
+    }
+
+    /**
+     * Verifies that the value is >= the minimum value.
+     *
+     * @param result where to add the validation result
+     * @param fieldName field whose value is being verified
+     * @param annot annotation against which the value is being verified
+     * @param value value to be verified
+     * @return {@code true} if the next check should be performed, {@code false} otherwise
+     */
+    public boolean verPfMin(BeanValidationResult result, String fieldName, PfMin annot, Object value) {
+        if (!(value instanceof Number num)) {
+            return true;
+        }
+
+        if (num.longValue() == annot.allowed()) {
+            // this value is always allowed
+            return true;
+        }
+
+        return verMin(result, fieldName, annot.value(), value);
+    }
+
+    /**
+     * Invokes the value's {@link Validated#validate(String) validate()} method, if the
+     * value is of type {@link Validated}.
+     */
+    @Override
+    public boolean verCascade(BeanValidationResult result, String fieldName, Object value) {
+        if (value instanceof Validated 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);
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/base/Validated.java b/policy-models/src/main/java/org/onap/policy/models/base/Validated.java
new file mode 100644 (file)
index 0000000..0c4f360
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019-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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+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;
+
+/**
+ * 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_BLANK = "is blank";
+    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_DEFINED = "not defined";
+    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}
+     * 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);
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/base/validation/annotations/PfMin.java b/policy-models/src/main/java/org/onap/policy/models/base/validation/annotations/PfMin.java
new file mode 100644 (file)
index 0000000..8b7190a
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * ============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.models.base.validation.annotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.TYPE_USE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Same as the "Min" annotation, but allows an extra value that is not in the range.
+ */
+@Retention(RUNTIME)
+@Target({FIELD, TYPE_USE})
+public @interface PfMin {
+
+    /**
+     * The minimum value allowed.
+     *
+     * @return the minimum value allowed
+     */
+    long value();
+
+    /**
+     * Allowed value.
+     */
+    long allowed();
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/base/validation/annotations/VerifyKey.java b/policy-models/src/main/java/org/onap/policy/models/base/validation/annotations/VerifyKey.java
new file mode 100644 (file)
index 0000000..cc8c882
--- /dev/null
@@ -0,0 +1,57 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base.validation.annotations;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Validates a key.
+ */
+@Retention(RUNTIME)
+@Target(FIELD)
+public @interface VerifyKey {
+
+    /**
+     * Validates that key.isNullKey() is {@code false}.
+     */
+    boolean keyNotNull() default true;
+
+    /**
+     * Validates that key.isNullName() is {@code false}.
+     */
+    boolean nameNotNull() default true;
+
+    /**
+     * Validates that key.isNullVersion() is {@code false}.
+     */
+    boolean versionNotNull() default false;
+
+    /**
+     * Invokes key.validate(), avoiding the need to include the "Valid" annotation. Note:
+     * if this is {@code true}, then the "Valid" annotation should not be specified, as
+     * that would result in duplicate validation checks.
+     */
+    boolean valid() default true;
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/errors/concepts/ErrorResponse.java b/policy-models/src/main/java/org/onap/policy/models/errors/concepts/ErrorResponse.java
new file mode 100644 (file)
index 0000000..b06037e
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Decision Models
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2023 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.errors.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import jakarta.ws.rs.core.Response;
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+
+/**
+ * This class is for defining a common error/warning
+ * response from API calls in the Policy Framework.
+ *
+ * @author pameladragosh
+ */
+@Data
+public class ErrorResponse implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 6760066094588944729L;
+
+    @SerializedName("code")
+    private Response.Status responseCode;
+    @SerializedName("error")
+    private String errorMessage;
+    @SerializedName("details")
+    private List<String> errorDetails;
+    @SerializedName("warnings")
+    private List<String> warningDetails;
+
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/errors/concepts/ErrorResponseInfo.java b/policy-models/src/main/java/org/onap/policy/models/errors/concepts/ErrorResponseInfo.java
new file mode 100644 (file)
index 0000000..70ebbef
--- /dev/null
@@ -0,0 +1,38 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ *  Modifications Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.errors.concepts;
+
+/**
+ * Interface implemented by Policy framework model exceptions to allow uniform reading of error responses.
+ *
+ * @author Liam Fallon (liam.fallon@est.tech)
+ */
+@FunctionalInterface
+public interface ErrorResponseInfo {
+
+    /**
+     * Get the error response.
+     *
+     * @return the error response
+     */
+    public ErrorResponse getErrorResponse();
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/errors/concepts/ErrorResponseUtils.java b/policy-models/src/main/java/org/onap/policy/models/errors/concepts/ErrorResponseUtils.java
new file mode 100644 (file)
index 0000000..e571e40
--- /dev/null
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019, 2024 Nordix Foundation.
+ *  Modifications 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.errors.concepts;
+
+import java.util.ArrayList;
+import java.util.List;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+/**
+ * Utility class for managing {@link ErrorResponse objects}.
+ *
+ * @author Liam Fallon (liam.fallon@est.tech)
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class ErrorResponseUtils {
+
+    /**
+     * Store the cascaded messages from an exception and all its nested exceptions in an ErrorResponse object.
+     *
+     * @param throwable the top level exception
+     */
+    public static void getExceptionMessages(final ErrorResponse errorResponse, final Throwable throwable) {
+        errorResponse.setErrorMessage(throwable.getMessage());
+
+        List<String> cascadedErrorMessages = new ArrayList<>();
+
+        for (var t = throwable; t != null; t = t.getCause()) {
+            cascadedErrorMessages.add(t.getMessage());
+        }
+
+        if (!cascadedErrorMessages.isEmpty()) {
+            errorResponse.setErrorDetails(cascadedErrorMessages);
+        }
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaCapabilityAssignment.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaCapabilityAssignment.java
new file mode 100644 (file)
index 0000000..11ffc04
--- /dev/null
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020-2021 Nordix Foundation.
+ * Modifications 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import lombok.ToString;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+@ToString(callSuper = true)
+public class ToscaCapabilityAssignment extends ToscaWithTypeAndObjectProperties {
+    private Map<String, Object> attributes;
+    private List<Object> occurrences;
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyObject object to copy
+     */
+    public ToscaCapabilityAssignment(@NonNull ToscaCapabilityAssignment copyObject) {
+        super(copyObject);
+
+        if (copyObject.attributes != null) {
+            attributes = new LinkedHashMap<>(copyObject.attributes);
+        }
+
+        if (copyObject.occurrences != null) {
+            occurrences = new ArrayList<>(copyObject.occurrences);
+        }
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaCapabilityType.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaCapabilityType.java
new file mode 100644 (file)
index 0000000..ad8da07
--- /dev/null
@@ -0,0 +1,35 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * Modifications 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class ToscaCapabilityType extends ToscaWithToscaProperties {
+
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaConceptIdentifier.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaConceptIdentifier.java
new file mode 100644 (file)
index 0000000..a243414
--- /dev/null
@@ -0,0 +1,72 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Models
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2020-2021 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.tosca.authorative.concepts;
+
+import java.io.Serializable;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import org.onap.policy.common.parameters.BeanValidationResult;
+import org.onap.policy.common.parameters.ValidationResult;
+import org.onap.policy.models.base.PfKey;
+
+/**
+ * Identifies a concept. Both the name and version must be non-null.
+ */
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class ToscaConceptIdentifier extends ToscaNameVersion
+                implements Serializable, Comparable<ToscaConceptIdentifier> {
+    private static final long serialVersionUID = 8010649773816325786L;
+
+
+    public ToscaConceptIdentifier(@NonNull String name, @NonNull String version) {
+        super(name, version);
+    }
+
+    public ToscaConceptIdentifier(@NonNull PfKey key) {
+        super(key);
+    }
+
+    public ToscaConceptIdentifier(ToscaConceptIdentifier source) {
+        super(source);
+    }
+
+    /**
+     * Validates that appropriate fields are populated for an incoming call to the PAP REST API.
+     *
+     * @return the validation result
+     */
+    public ValidationResult validatePapRest() {
+        var result = new BeanValidationResult("identifier", this);
+
+        result.validateNotNull("name", getName());
+        result.validateNotNull("version", getVersion());
+
+        return result;
+    }
+
+    @Override
+    public int compareTo(ToscaConceptIdentifier other) {
+        return commonCompareTo(other);
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaConstraint.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaConstraint.java
new file mode 100644 (file)
index 0000000..f00c243
--- /dev/null
@@ -0,0 +1,56 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2019-2021 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import java.util.List;
+import lombok.Data;
+
+/**
+ * Class to represent TOSCA constraint matching input/output from/to client.
+ *
+ * @author Chenfei Gao (cgao@research.att.com)
+ */
+@Data
+public class ToscaConstraint {
+    @SerializedName("valid_values")
+    private List<String> validValues;
+
+    private String equal;
+
+    @SerializedName("greater_than")
+    private String greaterThan;
+
+    @SerializedName("greater_or_equal")
+    private String greaterOrEqual;
+
+    @SerializedName("less_than")
+    private String lessThan;
+
+    @SerializedName("less_or_equal")
+    private String lessOrEqual;
+
+    @SerializedName("in_range")
+    private List<String> rangeValues;
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaDataType.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaDataType.java
new file mode 100644 (file)
index 0000000..6705e52
--- /dev/null
@@ -0,0 +1,41 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2019-2020 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+/**
+ * Class to represent TOSCA data type matching input/output from/to client.
+ *
+ * @author Chenfei Gao (cgao@research.att.com)
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class ToscaDataType extends ToscaWithToscaProperties {
+    private List<ToscaConstraint> constraints;
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaEntity.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaEntity.java
new file mode 100644 (file)
index 0000000..d5c098a
--- /dev/null
@@ -0,0 +1,166 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2019-2023 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import jakarta.ws.rs.core.Response;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import org.onap.policy.models.base.PfKey;
+import org.onap.policy.models.base.PfModelRuntimeException;
+import org.onap.policy.models.base.PfNameVersion;
+
+/**
+ * Class to represent TOSCA data type matching input/output from/to client.
+ *
+ * @author Chenfei Gao (cgao@research.att.com)
+ */
+@Data
+@NoArgsConstructor
+public class ToscaEntity implements PfNameVersion {
+    private String name = PfKey.NULL_KEY_NAME;
+    private String version = PfKey.NULL_KEY_VERSION;
+
+    @SerializedName("derived_from")
+    private String derivedFrom;
+
+    private Map<String, Object> metadata;
+    private String description;
+
+    /**
+     * Copy Constructor.
+     *
+     * @param copyObject object to copy from
+     */
+    public ToscaEntity(@NonNull ToscaEntity copyObject) {
+        this.name = copyObject.name;
+        this.version = copyObject.version;
+        this.derivedFrom = copyObject.derivedFrom;
+        this.description = copyObject.description;
+
+        if (copyObject.metadata != null) {
+            metadata = new LinkedHashMap<>();
+            for (final Entry<String, Object> metadataEntry : copyObject.metadata.entrySet()) {
+                metadata.put(metadataEntry.getKey(), metadataEntry.getValue());
+            }
+        }
+    }
+
+    /**
+     * Get a key for this entity.
+     *
+     * @return a ToscaEntityKey for this entry
+     */
+    public ToscaEntityKey getKey() {
+        return new ToscaEntityKey(name, version);
+    }
+
+    @Override
+    public String getDefinedName() {
+        return (PfKey.NULL_KEY_NAME.equals(name) ? null : name);
+    }
+
+    @Override
+    public String getDefinedVersion() {
+        return (PfKey.NULL_KEY_VERSION.equals(version) ? null : version);
+    }
+
+    /**
+     * Convert a list of maps of TOSCA entities into a regular map.
+     *
+     * @param listOfMapsOfEntities the incoming list of maps of entities
+     * @return The entities on a regular map
+     * @throws PfModelRuntimeException on duplicate entity entries
+     */
+    public static <T extends ToscaEntity> Map<ToscaEntityKey, T> getEntityListMapAsMap(
+            List<Map<String, T>> listOfMapsOfEntities) {
+        // Declare the return map
+        Map<ToscaEntityKey, T> entityMap = new LinkedHashMap<>();
+
+        if (listOfMapsOfEntities == null) {
+            return entityMap;
+        }
+
+        for (Map<String, T> mapOfEntities : listOfMapsOfEntities) {
+            for (T entityEntry : mapOfEntities.values()) {
+                if (entityMap.containsKey(entityEntry.getKey())) {
+                    throw new PfModelRuntimeException(Response.Status.INTERNAL_SERVER_ERROR,
+                        "list of map of entities contains more than one entity with key " + entityEntry.getKey());
+                }
+                entityMap.put(entityEntry.getKey(), entityEntry);
+            }
+        }
+
+        return entityMap;
+    }
+
+    /**
+     * Convert a map of TOSCA entities into a regular map.
+     *
+     * @param mapOfEntities the incoming list of maps of entities
+     * @return The entities on a regular map
+     * @throws PfModelRuntimeException on duplicate entity entries
+     */
+    public static <T extends ToscaEntity> Map<ToscaEntityKey, T> getEntityMapAsMap(Map<String, T> mapOfEntities) {
+        // Declare the return map
+        Map<ToscaEntityKey, T> entityMap = new LinkedHashMap<>();
+
+        if (mapOfEntities == null) {
+            return entityMap;
+        }
+
+        for (T entityEntry : mapOfEntities.values()) {
+            if (entityMap.containsKey(entityEntry.getKey())) {
+                throw new PfModelRuntimeException(Response.Status.INTERNAL_SERVER_ERROR,
+                    "list of map of entities contains more than one entity with key " + entityEntry.getKey());
+            }
+
+            entityMap.put(entityEntry.getKey(), entityEntry);
+        }
+
+        return entityMap;
+    }
+
+    /**
+     * Method that should be specialised to return the type of the entity if the entity has a type.
+     *
+     * @return the type of the entity or null if it has no type
+     */
+    public String getType() {
+        return null;
+    }
+
+    /**
+     * Method that should be specialised to return the type version of the entity if the entity has a type.
+     *
+     * @return the type of the entity or null if it has no type
+     */
+    public String getTypeVersion() {
+        return null;
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaEntityComparator.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaEntityComparator.java
new file mode 100644 (file)
index 0000000..9b8c986
--- /dev/null
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020-2021 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import java.util.Comparator;
+
+/**
+ * Compare two ToscaEntity objects.
+ */
+public class ToscaEntityComparator<T extends ToscaEntity> implements Comparator<T> {
+
+    @Override
+    public int compare(final ToscaEntity left, final ToscaEntity right) {
+        return left.compareNameVersion(left, right);
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaEntityKey.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaEntityKey.java
new file mode 100644 (file)
index 0000000..caf02fc
--- /dev/null
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019, 2021 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * This class is a compound key for Tosca entity keying on maps.
+ *
+ * @author Liam Fallon (liam.fallon@est.tech)
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class ToscaEntityKey {
+    private String name;
+    private String version;
+
+    public ToscaConceptIdentifier asIdentifier() {
+        return new ToscaConceptIdentifier(name, version);
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaNameVersion.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaNameVersion.java
new file mode 100644 (file)
index 0000000..d514acf
--- /dev/null
@@ -0,0 +1,90 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Models
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NonNull;
+import org.apache.commons.lang3.ObjectUtils;
+import org.onap.policy.models.base.PfConceptKey;
+import org.onap.policy.models.base.PfKey;
+
+/**
+ * Concept with an optional name and version.
+ */
+@Data
+@AllArgsConstructor
+public class ToscaNameVersion {
+
+    private String name;
+
+    private String version;
+
+    public ToscaNameVersion() {
+        this.name = null;
+        this.version = null;
+    }
+
+    public ToscaNameVersion(@NonNull PfKey key) {
+        this.name = key.getName();
+        this.version = key.getVersion();
+    }
+
+    public ToscaNameVersion(ToscaNameVersion source) {
+        this.name = source.name;
+        this.version = source.version;
+    }
+
+    /**
+     * Create a PfConcceptKey from the TOSCA identifier.
+     *
+     * @return the key
+     */
+    public PfConceptKey asConceptKey() {
+        return new PfConceptKey(name, version);
+    }
+
+    protected int commonCompareTo(ToscaNameVersion other) {
+        if (this == other) {
+            return 0;
+        }
+
+        if (other == null) {
+            return 1;
+        }
+
+        if (getClass() != other.getClass()) {
+            return getClass().getSimpleName().compareTo(other.getClass().getSimpleName());
+        }
+
+        int result = ObjectUtils.compare(getName(), other.getName());
+        if (result != 0) {
+            return result;
+        }
+
+        return ObjectUtils.compare(getVersion(), other.getVersion());
+    }
+
+    @Override
+    public String toString() {
+        return this.name + " " + this.version;
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaNodeTemplate.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaNodeTemplate.java
new file mode 100644 (file)
index 0000000..c95836d
--- /dev/null
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2020-2021 Nordix Foundation.
+ * Modifications 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import lombok.ToString;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+@ToString(callSuper = true)
+public class ToscaNodeTemplate extends ToscaWithTypeAndObjectProperties {
+    private List<Map<String, ToscaRequirement>> requirements;
+    private Map<String, ToscaCapabilityAssignment> capabilities;
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyObject the obejct to copy from.
+     */
+    public ToscaNodeTemplate(@NonNull ToscaNodeTemplate copyObject) {
+        super(copyObject);
+
+        this.requirements = (copyObject.requirements != null ? new ArrayList<>(copyObject.requirements) : null);
+        this.capabilities = (copyObject.capabilities != null ? new LinkedHashMap<>(copyObject.capabilities) : null);
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaNodeType.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaNodeType.java
new file mode 100644 (file)
index 0000000..6c03623
--- /dev/null
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * Modifications 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import java.util.List;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class ToscaNodeType extends ToscaWithToscaProperties {
+    private List<Map<String, ToscaRequirement>> requirements;
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaParameter.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaParameter.java
new file mode 100644 (file)
index 0000000..86557eb
--- /dev/null
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2020 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+public class ToscaParameter {
+    private String name;
+    private String type;
+
+    @SerializedName("type_version")
+
+    private String typeVersion;
+    private Object value;
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicy.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicy.java
new file mode 100644 (file)
index 0000000..00d783d
--- /dev/null
@@ -0,0 +1,50 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2019-2021 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import lombok.ToString;
+
+/**
+ * Class to represent TOSCA policy matching input/output from/to client.
+ *
+ * @author Chenfei Gao (cgao@research.att.com)
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+@ToString(callSuper = true)
+public class ToscaPolicy extends ToscaWithTypeAndObjectProperties {
+    /**
+     * Copy constructor.
+     *
+     * @param copyObject object to copy
+     */
+    public ToscaPolicy(@NonNull ToscaPolicy copyObject) {
+        super(copyObject);
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyType.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyType.java
new file mode 100644 (file)
index 0000000..671ba32
--- /dev/null
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2019-2020 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+
+/**
+ * Class to represent TOSCA policy type matching input/output from/to client.
+ *
+ * @author Chenfei Gao (cgao@research.att.com)
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class ToscaPolicyType extends ToscaWithToscaProperties {
+
+    /**
+     * Copy Constructor.
+     *
+     * @param copyObject object to copy from
+     */
+    public ToscaPolicyType(@NonNull ToscaPolicyType copyObject) {
+        super(copyObject);
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaProperty.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaProperty.java
new file mode 100644 (file)
index 0000000..977d327
--- /dev/null
@@ -0,0 +1,64 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2019-2020 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import java.util.List;
+import java.util.Map;
+import lombok.Data;
+
+/**
+ * Class to represent TOSCA property matching input/output from/to client.
+ *
+ * @author Chenfei Gao (cgao@research.att.com)
+ */
+@Data
+public class ToscaProperty {
+    public enum Status {
+        SUPPORTED, UNSUPPORTED, EXPERIMENTAL, DEPRECATED
+    }
+
+    private String name;
+    private String type;
+
+    @SerializedName("type_version")
+    private String typeVersion;
+
+    private String description;
+
+    @SerializedName("default")
+    private Object defaultValue;
+
+    private boolean required = false;
+    private Status status;
+    private List<ToscaConstraint> constraints;
+
+    @SerializedName("key_schema")
+    private ToscaSchemaDefinition keySchema;
+
+    @SerializedName("entry_schema")
+    private ToscaSchemaDefinition entrySchema;
+
+    private Map<String, String> metadata;
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaRelationshipType.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaRelationshipType.java
new file mode 100644 (file)
index 0000000..6b9415f
--- /dev/null
@@ -0,0 +1,35 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2020 Nordix Foundation.
+ * Modifications 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class ToscaRelationshipType extends ToscaWithToscaProperties {
+
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaRequirement.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaRequirement.java
new file mode 100644 (file)
index 0000000..d2c3b83
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020-2021 Nordix Foundation.
+ * Modifications 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import java.util.ArrayList;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import lombok.ToString;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+@ToString(callSuper = true)
+public class ToscaRequirement extends ToscaWithTypeAndObjectProperties {
+    private String capability;
+    private String node;
+    private String relationship;
+    private List<Object> occurrences;
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyObject object to copy
+     */
+    public ToscaRequirement(@NonNull ToscaRequirement copyObject) {
+        super(copyObject);
+
+        this.capability = copyObject.capability;
+        this.node = copyObject.node;
+        this.relationship = copyObject.relationship;
+
+        if (copyObject.occurrences != null) {
+            occurrences = new ArrayList<>(copyObject.occurrences);
+        }
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaSchemaDefinition.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaSchemaDefinition.java
new file mode 100644 (file)
index 0000000..d89af6a
--- /dev/null
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2019 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import java.util.List;
+import lombok.Data;
+
+/**
+ * Class to represent TOSCA schema matching input/output from/to client.
+ *
+ * @author Chenfei Gao (cgao@research.att.com)
+ */
+@Data
+public class ToscaSchemaDefinition {
+    private String name;
+    private String type;
+
+    @SerializedName("type_version")
+    private String typeVersion;
+
+    private String description;
+    private List<ToscaConstraint> constraints;
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaServiceTemplate.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaServiceTemplate.java
new file mode 100644 (file)
index 0000000..1914280
--- /dev/null
@@ -0,0 +1,104 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2019-2021 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+
+/**
+ * Class to represent TOSCA service template matching input/output from/to client.
+ *
+ * @author Chenfei Gao (cgao@research.att.com)
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class ToscaServiceTemplate extends ToscaEntity {
+    @SerializedName("tosca_definitions_version")
+    private String toscaDefinitionsVersion;
+
+    @SerializedName("data_types")
+    private Map<String, ToscaDataType> dataTypes;
+
+    @SerializedName("capability_types")
+    private Map<String, ToscaCapabilityType> capabilityTypes;
+
+    @SerializedName("node_types")
+    private Map<String, ToscaNodeType> nodeTypes;
+
+    @SerializedName("relationship_types")
+    private Map<String, ToscaRelationshipType> relationshipTypes;
+
+    @SerializedName("policy_types")
+    private Map<String, ToscaPolicyType> policyTypes;
+
+    @SerializedName("topology_template")
+    private ToscaTopologyTemplate toscaTopologyTemplate;
+
+    public Map<ToscaEntityKey, ToscaDataType> getDataTypesAsMap() {
+        return ToscaEntity.getEntityMapAsMap(dataTypes);
+    }
+
+    public Map<ToscaEntityKey, ToscaPolicyType> getPolicyTypesAsMap() {
+        return ToscaEntity.getEntityMapAsMap(policyTypes);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyObject the obejct to copy from.
+     */
+    public ToscaServiceTemplate(@NonNull ToscaServiceTemplate copyObject) {
+        super(copyObject);
+
+        this.toscaDefinitionsVersion = copyObject.toscaDefinitionsVersion;
+
+        // @formatter:off
+        this.dataTypes         = (copyObject.dataTypes         != null
+                ? new LinkedHashMap<>(copyObject.dataTypes)
+                : null);
+        this.capabilityTypes   = (copyObject.capabilityTypes   != null
+                ? new LinkedHashMap<>(copyObject.capabilityTypes)
+                : null);
+        this.nodeTypes         = (copyObject.nodeTypes         != null
+                ? new LinkedHashMap<>(copyObject.nodeTypes)
+                : null);
+        this.relationshipTypes = (copyObject.relationshipTypes != null
+                ? new LinkedHashMap<>(copyObject.relationshipTypes)
+                : null);
+        this.policyTypes       = (copyObject.policyTypes       != null
+                ? new LinkedHashMap<>(copyObject.policyTypes)
+                : null);
+        // @formatter:on
+
+        this.toscaTopologyTemplate =
+                (copyObject.toscaTopologyTemplate != null ? new ToscaTopologyTemplate(copyObject.toscaTopologyTemplate)
+                        : null);
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaServiceTemplates.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaServiceTemplates.java
new file mode 100644 (file)
index 0000000..4c145cc
--- /dev/null
@@ -0,0 +1,38 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2020 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * Class to represent a map of TOSCA service templates.
+ */
+@Data
+@EqualsAndHashCode
+public class ToscaServiceTemplates {
+    @SerializedName("service_templates")
+    private List<ToscaServiceTemplate> serviceTemplates;
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaTopologyTemplate.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaTopologyTemplate.java
new file mode 100644 (file)
index 0000000..45b4b20
--- /dev/null
@@ -0,0 +1,70 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2020-2021 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+
+/**
+ * Class to represent TOSCA topology template matching input/output from/to client.
+ *
+ * @author Chenfei Gao (cgao@research.att.com)
+ */
+@Data
+@NoArgsConstructor
+public class ToscaTopologyTemplate {
+    private String description;
+
+    private Map<String, ToscaParameter> inputs;
+
+    @SerializedName("node_templates")
+    private Map<String, ToscaNodeTemplate> nodeTemplates;
+
+    private List<Map<String, ToscaPolicy>> policies;
+
+    public Map<ToscaEntityKey, ToscaPolicy> getPoliciesAsMap() {
+        return ToscaEntity.getEntityListMapAsMap(policies);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyObject the obejct to copy from.
+     */
+    public ToscaTopologyTemplate(@NonNull ToscaTopologyTemplate copyObject) {
+        this.description = copyObject.description;
+
+        // @formatter:off
+        this.inputs        = (copyObject.inputs        != null ? new LinkedHashMap<>(copyObject.inputs)        : null);
+        this.nodeTemplates = (copyObject.nodeTemplates != null ? new LinkedHashMap<>(copyObject.nodeTemplates) : null);
+        this.policies      = (copyObject.policies      != null ? new ArrayList<>(copyObject.policies)          : null);
+        // @formatter:on
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaWithToscaProperties.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaWithToscaProperties.java
new file mode 100644 (file)
index 0000000..49332bd
--- /dev/null
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+
+/**
+ * Class to represent TOSCA classes containing TOSCA properties.
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class ToscaWithToscaProperties extends ToscaEntity {
+    private Map<String, ToscaProperty> properties;
+
+    /**
+     * Copy Constructor.
+     *
+     * @param copyObject object to copy from
+     */
+    public ToscaWithToscaProperties(@NonNull ToscaWithToscaProperties copyObject) {
+        super(copyObject);
+
+        if (copyObject.properties != null) {
+            properties = new LinkedHashMap<>(copyObject.properties);
+        }
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaWithTypeAndObjectProperties.java b/policy-models/src/main/java/org/onap/policy/models/tosca/authorative/concepts/ToscaWithTypeAndObjectProperties.java
new file mode 100644 (file)
index 0000000..ff862cb
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2021 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import lombok.ToString;
+
+/**
+ * Class to represent TOSCA classes containing property maps whose values are generic
+ * Objects.
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+@ToString
+public class ToscaWithTypeAndObjectProperties extends ToscaEntity {
+    private String type;
+
+    @SerializedName("type_version")
+    private String typeVersion;
+
+    private Map<String, Object> properties;
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyObject object to copy
+     */
+    public ToscaWithTypeAndObjectProperties(@NonNull ToscaWithTypeAndObjectProperties copyObject) {
+        super(copyObject);
+
+        this.type = copyObject.type;
+        this.typeVersion = copyObject.typeVersion;
+
+        if (copyObject.properties != null) {
+            properties = new LinkedHashMap<>(copyObject.properties);
+        }
+    }
+
+    /**
+     * Gets the identifier for this policy.
+     *
+     * @return this policy's identifier
+     */
+    public ToscaConceptIdentifier getIdentifier() {
+        return new ToscaConceptIdentifier(getName(), getVersion());
+    }
+
+    /**
+     * Gets the type identifier for this policy.
+     *
+     * @return this policy's type identifier
+     */
+    public ToscaConceptIdentifier getTypeIdentifier() {
+        return new ToscaConceptIdentifier(getType(), getTypeVersion());
+    }
+}
diff --git a/policy-models/src/main/java/org/onap/policy/models/tosca/utils/ToscaUtils.java b/policy-models/src/main/java/org/onap/policy/models/tosca/utils/ToscaUtils.java
new file mode 100644 (file)
index 0000000..99873e8
--- /dev/null
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019-2025 OpenInfra Foundation Europe. All rights reserved.
+ *  Modifications 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.utils;
+
+import java.util.Collection;
+import java.util.Set;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.onap.policy.models.base.PfConceptKey;
+import org.onap.policy.models.base.PfKey;
+
+/**
+ * Utility class for TOSCA concepts.
+ *
+ * @author Liam Fallon (liam.fallon@est.tech)
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class ToscaUtils {
+    private static final String ROOT_KEY_NAME_SUFFIX = ".Root";
+
+    // @formatter:off
+    private static final Set<PfConceptKey> PREDEFINED_TOSCA_DATA_TYPES = Set.of(
+            new PfConceptKey("string",                       PfKey.NULL_KEY_VERSION),
+            new PfConceptKey("integer",                      PfKey.NULL_KEY_VERSION),
+            new PfConceptKey("float",                        PfKey.NULL_KEY_VERSION),
+            new PfConceptKey("boolean",                      PfKey.NULL_KEY_VERSION),
+            new PfConceptKey("timestamp",                    PfKey.NULL_KEY_VERSION),
+            new PfConceptKey("null",                         PfKey.NULL_KEY_VERSION),
+            new PfConceptKey("list",                         PfKey.NULL_KEY_VERSION),
+            new PfConceptKey("map",                          PfKey.NULL_KEY_VERSION),
+            new PfConceptKey("object",                       PfKey.NULL_KEY_VERSION),
+            new PfConceptKey("scalar-unit.size",             PfKey.NULL_KEY_VERSION),
+            new PfConceptKey("scalar-unit.time",             PfKey.NULL_KEY_VERSION),
+            new PfConceptKey("scalar-unit.frequency",        PfKey.NULL_KEY_VERSION),
+            new PfConceptKey("tosca.datatypes.TimeInterval", PfKey.NULL_KEY_VERSION)
+        );
+    // @formatter:on
+
+    /**
+     * Get the predefined policy types.
+     *
+     * @return the predefined policy types
+     */
+    public static Collection<PfConceptKey> getPredefinedDataTypes() {
+        return PREDEFINED_TOSCA_DATA_TYPES;
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/base/ExceptionsTest.java b/policy-models/src/test/java/org/onap/policy/models/base/ExceptionsTest.java
new file mode 100644 (file)
index 0000000..20c2ae3
--- /dev/null
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019, 2021, 2023, 2024 Nordix Foundation.
+ * Modifications Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+import java.io.IOException;
+import org.junit.jupiter.api.Test;
+import org.onap.policy.models.errors.concepts.ErrorResponse;
+
+class ExceptionsTest {
+
+    private static final String STRING_TEXT = "String";
+    private static final String MESSAGE = "Message";
+
+    @Test
+    void test() {
+        assertNotNull(new PfModelException(Response.Status.OK, MESSAGE));
+        assertNotNull(new PfModelException(Response.Status.OK, MESSAGE, STRING_TEXT));
+        assertNotNull(new PfModelException(Response.Status.OK, MESSAGE, new IOException()));
+        assertNotNull(new PfModelException(Response.Status.OK, MESSAGE, new IOException(), STRING_TEXT));
+
+        String key = "A String";
+        PfModelException ae =
+            new PfModelException(Response.Status.OK, MESSAGE, new IOException("IO exception message"), key);
+        ErrorResponse errorResponse = ae.getErrorResponse();
+        assertEquals("Message\nIO exception message", String.join("\n", errorResponse.getErrorDetails()));
+        assertEquals(key, ae.getObject());
+
+        assertNotNull(new PfModelRuntimeException(Response.Status.OK, MESSAGE));
+        assertNotNull(new PfModelRuntimeException(Response.Status.OK, MESSAGE, STRING_TEXT));
+        assertNotNull(new PfModelRuntimeException(Response.Status.OK, MESSAGE, new IOException()));
+        assertNotNull(new PfModelRuntimeException(Response.Status.OK, MESSAGE, new IOException(), STRING_TEXT));
+
+        String rkey = "A String";
+        PfModelRuntimeException re = new PfModelRuntimeException(Response.Status.OK, "Runtime Message",
+            new IOException("IO runtime exception message"), rkey);
+        errorResponse = re.getErrorResponse();
+        assertEquals("Runtime Message\nIO runtime exception message",
+            String.join("\n", errorResponse.getErrorDetails()));
+        assertEquals(key, re.getObject());
+
+        PfModelRuntimeException pfre = new PfModelRuntimeException(ae);
+        assertEquals(ae.getErrorResponse().getResponseCode(), pfre.getErrorResponse().getResponseCode());
+        assertEquals(ae.getMessage(), pfre.getMessage());
+
+        try {
+            try {
+                throw new PfModelException(Status.BAD_GATEWAY, "An Exception");
+            } catch (PfModelException pfme) {
+                throw new PfModelRuntimeException(pfme);
+            }
+        } catch (PfModelRuntimeException pfmre) {
+            assertEquals(Status.BAD_GATEWAY, pfmre.getErrorResponse().getResponseCode());
+            assertEquals("An Exception", pfmre.getMessage());
+            assertEquals(PfModelException.class.getName(), pfmre.getCause().getClass().getName());
+        }
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/base/PfConceptKeyTest.java b/policy-models/src/test/java/org/onap/policy/models/base/PfConceptKeyTest.java
new file mode 100644 (file)
index 0000000..277c927
--- /dev/null
@@ -0,0 +1,79 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019-2020, 2024 Nordix Foundation.
+ *  Modifications Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+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 static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+import org.onap.policy.models.base.testconcepts.DummyPfConcept;
+
+class PfConceptKeyTest {
+
+    private static final String VERSION001 = "0.0.1";
+    private static final String ID_IS_NULL = "id is marked .*on.*ull but is null$";
+
+    @Test
+    void testConceptKey() {
+        PfConceptKey someKey0 = new PfConceptKey();
+        assertEquals(PfConceptKey.getNullKey(), someKey0);
+        assertTrue(someKey0.isNullKey());
+        assertEquals("PfConceptKey(name=NULL, version=0.0.0)", someKey0.toString());
+
+        PfConceptKey someKey1 = new PfConceptKey("my-name", VERSION001);
+        PfConceptKey someKey2 = new PfConceptKey(someKey1);
+        PfConceptKey someKey3 = new PfConceptKey(someKey1.getId());
+        assertEquals(someKey1, someKey2);
+        assertEquals(someKey1, someKey3);
+        assertFalse(someKey1.isNullVersion());
+        assertFalse(someKey1.isNullName());
+        assertEquals("PfConceptKey(name=my-name, version=0.0.1)", someKey1.toString());
+
+        assertEquals("my-name", someKey1.getName());
+        assertEquals(VERSION001, someKey1.getVersion());
+
+        assertEquals(someKey2, someKey1.getKey());
+        assertEquals(1, someKey1.getKeys().size());
+
+        PfConcept pfc = new DummyPfConcept();
+        assertEquals(PfConceptKey.getNullKey().getId(), pfc.getId());
+
+        assertTrue(PfConceptKey.getNullKey().matchesId(pfc.getId()));
+
+        assertTrue(PfConceptKey.getNullKey().isNullKey());
+
+        assertThatThrownBy(() -> PfConceptKey.getNullKey().matchesId(null)).hasMessageMatching(ID_IS_NULL);
+
+        assertThatThrownBy(() -> someKey0.setName(null)).isInstanceOf(NullPointerException.class)
+            .hasMessageMatching("^name is marked .*on.*ull but is null$");
+
+        assertThatThrownBy(() -> someKey0.setVersion(null)).isInstanceOf(NullPointerException.class)
+            .hasMessageMatching("^version is marked .*on.*ull but is null$");
+
+        assertThatIllegalArgumentException().isThrownBy(() -> new PfConceptKey("my-name.*", VERSION001)).withMessage(
+            "parameter 'name': value 'my-name.*', does not match regular expression '^[A-Za-z0-9\\-_\\.]+$'"
+                .replace('\'', '"'));
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/base/PfKeyImplTest.java b/policy-models/src/test/java/org/onap/policy/models/base/PfKeyImplTest.java
new file mode 100644 (file)
index 0000000..78bb663
--- /dev/null
@@ -0,0 +1,335 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019-2021, 2023, 2024 Nordix Foundation.
+ *  Modifications Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+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 static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.lang.reflect.Field;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.onap.policy.common.parameters.ValidationResult;
+import org.onap.policy.common.parameters.annotations.Pattern;
+import org.onap.policy.models.base.PfKey.Compatibility;
+import org.onap.policy.models.base.testconcepts.DummyPfKey;
+
+class PfKeyImplTest {
+
+    private static final String OTHER_IS_NULL = "^otherKey is marked .*on.*ull but is null$";
+    private static final String ID_IS_NULL = "^id is marked .*on.*ull but is null$";
+    private static final String VERSION123 = "1.2.3";
+    private static final String VERSION100 = "1.0.0";
+    private static final String VERSION001 = "0.0.1";
+    private static final String NAME = "name";
+    private static MyKey someKey;
+    private static MyKey someKey0;
+    private static MyKey someKey1;
+    private static MyKey someKey2;
+    private static MyKey someKey3;
+    private static MyKey someKey4;
+    private static MyKey someKey4a;
+    private static MyKey someKey5;
+    private static MyKey someKey6;
+
+    private static final MyKey buildKey1 = new MyKey(NAME, "0.0.3+1");
+    private static final MyKey buildKey2 = new MyKey(NAME, "0.1.0-1");
+    private static final MyKey buildKey3 = new MyKey(NAME, "3.0.0-SNAPSHOT");
+    private static final MyKey buildKey4 = new MyKey(NAME, "1.0.0-rc.1");
+
+    /**
+     * Sets data in Keys for the tests.
+     */
+    @BeforeAll
+    static void setUp() {
+        someKey = new MyKey();
+
+        someKey0 = new MyKey();
+        someKey1 = new MyKey(NAME, VERSION001);
+        someKey2 = new MyKey(someKey1);
+        someKey3 = new MyKey(someKey1.getId());
+
+        someKey0.setName("zero");
+        someKey0.setVersion("0.0.2");
+        someKey3.setVersion("0.0.2");
+
+        someKey4 = new MyKey(someKey1);
+        someKey4.setVersion("0.1.2");
+
+        someKey4a = new MyKey(someKey1);
+        someKey4a.setVersion("0.0.0");
+
+        someKey5 = new MyKey(someKey1);
+        someKey5.setVersion("1.2.2");
+
+        someKey6 = new MyKey(someKey1);
+        someKey6.setVersion("3.0.0");
+    }
+
+    @Test
+    void testConceptKey() {
+        assertThatIllegalArgumentException().isThrownBy(() -> new MyKey("some bad key id"))
+            .withMessage("parameter \"id\": value \"some bad key id\", " + "does not match regular expression \""
+                + PfKey.KEY_ID_REGEXP + "\"");
+
+        assertThatThrownBy(() -> new MyKey((MyKey) null))
+            .hasMessageMatching("^copyConcept is marked .*on.*ull but is null$");
+
+        assertTrue(someKey.isNullKey());
+        assertEquals(new MyKey(PfKey.NULL_KEY_NAME, PfKey.NULL_KEY_VERSION), someKey);
+
+        MyKey someKey11 = new MyKey(NAME, VERSION001);
+        MyKey someKey22 = new MyKey(someKey11);
+        MyKey someKey33 = new MyKey(someKey11.getId());
+        assertEquals(someKey11, someKey22);
+        assertEquals(someKey11, someKey33);
+        assertFalse(someKey11.isNullKey());
+        assertFalse(someKey11.isNullVersion());
+
+        assertEquals(someKey22, someKey11.getKey());
+        assertEquals(1, someKey11.getKeys().size());
+    }
+
+    @Test
+    void testCompatibilityConceptKey() {
+        assertEquals("name:0.1.2", someKey4.getId());
+
+        assertThatThrownBy(() -> someKey0.getCompatibility(null)).isInstanceOf(NullPointerException.class)
+            .hasMessageMatching("^otherKey is marked .*on.*ull but is null$");
+
+        assertEquals(Compatibility.DIFFERENT, someKey0.getCompatibility(new DummyPfKey()));
+        assertEquals(Compatibility.DIFFERENT, buildKey1.getCompatibility(new DummyPfKey()));
+        assertEquals(Compatibility.DIFFERENT, someKey0.getCompatibility(someKey1));
+        assertEquals(Compatibility.IDENTICAL, someKey2.getCompatibility(someKey1));
+        assertEquals(Compatibility.IDENTICAL, buildKey1.getCompatibility(new MyKey(buildKey1)));
+        assertEquals(Compatibility.PATCH, someKey3.getCompatibility(someKey1));
+        assertEquals(Compatibility.PATCH, buildKey1.getCompatibility(someKey1));
+        assertEquals(Compatibility.MINOR, someKey4.getCompatibility(someKey1));
+        assertEquals(Compatibility.MINOR, buildKey2.getCompatibility(buildKey1));
+        assertEquals(Compatibility.PATCH, someKey4a.getCompatibility(someKey1));
+        assertEquals(Compatibility.PATCH, someKey1.getCompatibility(someKey4a));
+        assertEquals(Compatibility.MAJOR, someKey5.getCompatibility(someKey1));
+        assertEquals(Compatibility.MAJOR, someKey6.getCompatibility(someKey1));
+        assertEquals(Compatibility.MAJOR, buildKey3.getCompatibility(someKey1));
+
+        assertTrue(someKey1.isCompatible(someKey2));
+        assertTrue(someKey1.isCompatible(someKey3));
+        assertTrue(someKey1.isCompatible(someKey4));
+        assertFalse(someKey1.isCompatible(someKey0));
+        assertFalse(someKey1.isCompatible(someKey5));
+        assertFalse(someKey1.isCompatible(buildKey3));
+        assertFalse(someKey1.isCompatible(buildKey4));
+        assertFalse(someKey1.isCompatible(new DummyPfKey()));
+    }
+
+    @Test
+    void testValidityConceptKey() {
+        assertTrue(someKey0.validate("").isValid());
+        assertTrue(someKey1.validate("").isValid());
+        assertTrue(someKey2.validate("").isValid());
+        assertTrue(someKey3.validate("").isValid());
+        assertTrue(someKey4.validate("").isValid());
+        assertTrue(someKey5.validate("").isValid());
+        assertTrue(someKey6.validate("").isValid());
+        assertTrue(buildKey1.validate("").isValid());
+        assertTrue(buildKey2.validate("").isValid());
+        assertTrue(buildKey3.validate("").isValid());
+        assertTrue(buildKey4.validate("").isValid());
+    }
+
+    @Test
+    void testCleanConceptKey() {
+        someKey0.clean();
+        assertNotNull(someKey0.toString());
+
+        MyKey someKey7 = new MyKey(someKey1);
+        assertEquals(244799191, someKey7.hashCode());
+        assertEquals(0, someKey7.compareTo(someKey1));
+        assertEquals(-12, someKey7.compareTo(someKey0));
+
+        assertThatThrownBy(() -> someKey0.compareTo(null)).isInstanceOf(NullPointerException.class)
+            .hasMessageMatching("^otherObj is marked .*on.*ull but is null$");
+
+        assertEquals(0, someKey0.compareTo(someKey0));
+        assertEquals(-36, someKey0.compareTo(new DummyPfKey()));
+
+        MyKey someKey8 = new MyKey();
+        someKey8.setVersion(VERSION001);
+        assertFalse(someKey8.isNullKey());
+
+        someKey8.setVersion("10");
+        assertEquals(0, someKey8.getMinorVersion());
+
+        someKey8.setVersion("10.11");
+        assertEquals(0, someKey8.getPatchVersion());
+    }
+
+    @Test
+    void testNullArguments() {
+        assertThatThrownBy(() -> new MyKey((String) null)).hasMessageMatching(ID_IS_NULL);
+
+        assertThatThrownBy(() -> new MyKey((MyKey) null))
+            .hasMessageMatching("^copyConcept is marked .*on.*ull but is null$");
+
+        assertThatThrownBy(() -> new MyKey(null, null)).hasMessageMatching("name is marked .*on.*ull but is null$");
+
+        assertThatThrownBy(() -> new MyKey(NAME, null))
+            .hasMessageMatching("^version is marked .*on.*ull but is null$");
+
+        assertThatThrownBy(() -> new MyKey(null, VERSION001))
+            .hasMessageMatching("^name is marked .*on.*ull but is null$");
+
+        assertThatThrownBy(() -> new MyKey("AKey", VERSION001).isCompatible(null)).hasMessageMatching(OTHER_IS_NULL);
+    }
+
+    @Test
+    void testValidation() throws Exception {
+        MyKey testKey = new MyKey("TheKey", VERSION001);
+        assertEquals("TheKey:0.0.1", testKey.getId());
+
+        Field nameField = testKey.getClass().getDeclaredField(NAME);
+        nameField.setAccessible(true);
+        nameField.set(testKey, "Key Name");
+        ValidationResult validationResult = testKey.validate("");
+        nameField.set(testKey, "TheKey");
+        nameField.setAccessible(false);
+        assertThat(validationResult.getResult()).contains("\"name\"").doesNotContain("\"version\"")
+            .contains("does not match regular expression " + PfKey.NAME_REGEXP);
+
+        Field versionField = testKey.getClass().getDeclaredField("version");
+        versionField.setAccessible(true);
+        versionField.set(testKey, "Key Version");
+        ValidationResult validationResult2 = testKey.validate("");
+        versionField.set(testKey, VERSION001);
+        versionField.setAccessible(false);
+        assertThat(validationResult2.getResult()).doesNotContain("\"name\"").contains("\"version\"")
+            .contains("does not match regular expression " + PfKey.VERSION_REGEXP);
+    }
+
+    @Test
+    void testkeynewerThan() {
+        MyKey key1 = new MyKey("Key1", VERSION123);
+
+        assertThatThrownBy(() -> key1.isNewerThan(null)).hasMessageMatching(OTHER_IS_NULL);
+
+        assertThatThrownBy(() -> key1.isNewerThan(new PfReferenceKey())).hasMessage(
+            "org.onap.policy.models.base.PfReferenceKey is not " + "an instance of " + PfKeyImpl.class.getName());
+
+        assertFalse(key1.isNewerThan(key1));
+
+        MyKey key1a = new MyKey("Key1a", VERSION123);
+        assertFalse(key1.isNewerThan(key1a));
+
+        MyKey key1b = new MyKey("Key0", VERSION123);
+        assertTrue(key1.isNewerThan(key1b));
+
+        key1a.setName("Key1");
+        assertFalse(key1.isNewerThan(key1a));
+
+        key1a.setVersion("0.2.3");
+        assertTrue(key1.isNewerThan(key1a));
+        key1a.setVersion("2.2.3");
+        assertFalse(key1.isNewerThan(key1a));
+        key1a.setVersion(VERSION123);
+        assertFalse(key1.isNewerThan(key1a));
+
+        key1a.setVersion("1.1.3");
+        assertTrue(key1.isNewerThan(key1a));
+        key1a.setVersion("1.3.3");
+        assertFalse(key1.isNewerThan(key1a));
+        key1a.setVersion(VERSION123);
+        assertFalse(key1.isNewerThan(key1a));
+
+        key1a.setVersion("1.2.2");
+        assertTrue(key1.isNewerThan(key1a));
+        key1a.setVersion("1.2.4");
+        assertFalse(key1.isNewerThan(key1a));
+        key1a.setVersion(VERSION123);
+        assertFalse(key1.isNewerThan(key1a));
+
+        key1.setVersion(VERSION100);
+        assertFalse(key1.isNewerThan(key1a));
+        key1a.setVersion(VERSION100);
+        assertFalse(key1.isNewerThan(key1a));
+
+        PfReferenceKey refKey = new PfReferenceKey();
+
+        assertThatThrownBy(() -> refKey.isNewerThan(null)).hasMessageMatching(OTHER_IS_NULL);
+
+        assertThatThrownBy(() -> refKey.isNewerThan(new MyKey()))
+            .hasMessage(MyKey.class.getName() + " is not an instance of " + PfReferenceKey.class.getName());
+
+        assertFalse(refKey.isNewerThan(refKey));
+    }
+
+    @Test
+    void testmajorMinorPatch() {
+        MyKey key = new MyKey("Key", VERSION100);
+        assertEquals(1, key.getMajorVersion());
+        assertEquals(0, key.getMinorVersion());
+        assertEquals(0, key.getPatchVersion());
+
+        key = new MyKey("Key", "1.2.0");
+        assertEquals(1, key.getMajorVersion());
+        assertEquals(2, key.getMinorVersion());
+        assertEquals(0, key.getPatchVersion());
+
+        key = new MyKey("Key", VERSION123);
+        assertEquals(1, key.getMajorVersion());
+        assertEquals(2, key.getMinorVersion());
+        assertEquals(3, key.getPatchVersion());
+    }
+
+    @Getter
+    @Setter
+    @EqualsAndHashCode(callSuper = false)
+    @NoArgsConstructor
+    public static class MyKey extends PfKeyImpl {
+        private static final long serialVersionUID = 1L;
+
+        @Pattern(regexp = NAME_REGEXP)
+        private String name;
+
+        @Pattern(regexp = VERSION_REGEXP)
+        private String version;
+
+        public MyKey(String name, String version) {
+            super(name, version);
+        }
+
+        public MyKey(String id) {
+            super(id);
+        }
+
+        public MyKey(MyKey myKey) {
+            super(myKey);
+        }
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/base/PfModelExceptionInfoTest.java b/policy-models/src/test/java/org/onap/policy/models/base/PfModelExceptionInfoTest.java
new file mode 100644 (file)
index 0000000..d570099
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019-2020, 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import jakarta.ws.rs.core.Response;
+import org.junit.jupiter.api.Test;
+import org.onap.policy.models.errors.concepts.ErrorResponseInfo;
+
+/**
+ * Test PfModelExceptionInfo interface.
+ *
+ * @author Liam Fallon (liam.fallon@est.tech)
+ */
+class PfModelExceptionInfoTest {
+
+    @Test
+    void testExceptionInfo() {
+        final PfModelException pfme = new PfModelException(Response.Status.ACCEPTED, "HELLO");
+        assertThat(pfme).hasMessage("HELLO");
+        assertEquals("Server returned: Accepted", getErrorMessage(pfme).substring(0, 25));
+        assertNotNull(pfme.toString());
+
+        final PfModelRuntimeException pfmr = new PfModelRuntimeException(Response.Status.ACCEPTED, "HELLO");
+        assertThat(pfmr).hasMessage("HELLO");
+        assertEquals("Server returned: Accepted", getErrorMessage(pfmr).substring(0, 25));
+        assertNotNull(pfmr.toString());
+    }
+
+    private String getErrorMessage(final ErrorResponseInfo eri) {
+        StringBuilder stringBuilder = new StringBuilder();
+
+        stringBuilder.append("Server returned: ");
+        stringBuilder.append(eri.getErrorResponse().getResponseCode().toString());
+        stringBuilder.append("Error Message:\n");
+        stringBuilder.append(eri.getErrorResponse().getErrorMessage());
+        stringBuilder.append("\nDetailed Message:\n");
+        stringBuilder.append(String.join("\n", eri.getErrorResponse().getErrorDetails()));
+
+        return stringBuilder.toString();
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/base/PfNameVersionTest.java b/policy-models/src/test/java/org/onap/policy/models/base/PfNameVersionTest.java
new file mode 100644 (file)
index 0000000..6272404
--- /dev/null
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019-2020, 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+import org.onap.policy.models.base.testconcepts.DummyPfNameVersion;
+
+/**
+ * Test the {@link PfNameVersion} interface.
+ *
+ * @author Liam Fallon (liam.fallon@est.tech)
+ */
+class PfNameVersionTest {
+
+    @Test
+    void testPfNameVersion() {
+        DummyPfNameVersion dnv0 = new DummyPfNameVersion();
+        DummyPfNameVersion dnv1 = new DummyPfNameVersion();
+
+        assertEquals(0, dnv0.compareNameVersion(dnv0, dnv1));
+        assertEquals(0, dnv0.compareNameVersion(null, null));
+        assertEquals(-1, dnv0.compareNameVersion(dnv0, null));
+        assertEquals(1, dnv0.compareNameVersion(null, dnv1));
+
+        dnv1.setName("name1");
+        assertEquals(-1, dnv0.compareNameVersion(dnv0, dnv1));
+
+        dnv0.setName("name0");
+        assertEquals(-1, dnv0.compareNameVersion(dnv0, dnv1));
+
+        dnv1.setName("name0");
+        assertEquals(0, dnv0.compareNameVersion(dnv0, dnv1));
+
+        dnv1.setVersion("4.5.6");
+        assertEquals(1, dnv0.compareNameVersion(dnv0, dnv1));
+
+        dnv0.setVersion("1.2.3");
+        assertEquals(-1, dnv0.compareNameVersion(dnv0, dnv1));
+
+        dnv1.setVersion(null);
+        assertEquals(-1, dnv0.compareNameVersion(dnv0, dnv1));
+
+        dnv1.setVersion("1.2.3");
+        assertEquals(0, dnv0.compareNameVersion(dnv0, dnv1));
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/base/PfReferenceKeyTest.java b/policy-models/src/test/java/org/onap/policy/models/base/PfReferenceKeyTest.java
new file mode 100644 (file)
index 0000000..35535e7
--- /dev/null
@@ -0,0 +1,194 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019-2021, 2024 Nordix Foundation.
+ *  Modifications Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import static org.assertj.core.api.Assertions.assertThat;
+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 static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.lang.reflect.Field;
+import org.junit.jupiter.api.Test;
+import org.onap.policy.common.parameters.ValidationResult;
+
+class PfReferenceKeyTest {
+
+    private static final String PARENT_LOCAL_NAME = "ParentLocalName";
+    private static final String NPKLN = "NPKLN";
+    private static final String LOCAL_NAME = "LocalName";
+    private static final String VERSION002 = "0.0.2";
+    private static final String VERSION001 = "0.0.1";
+
+    @Test
+    void testPfReferenceKeyNotNull() {
+        assertNotNull(new PfReferenceKey());
+        assertNotNull(new PfReferenceKey(new PfConceptKey()));
+        assertNotNull(new PfReferenceKey(new PfConceptKey(), LOCAL_NAME));
+        assertNotNull(new PfReferenceKey(new PfReferenceKey()));
+        assertNotNull(new PfReferenceKey(new PfReferenceKey(), LOCAL_NAME));
+        assertNotNull(new PfReferenceKey(new PfConceptKey(), PARENT_LOCAL_NAME, LOCAL_NAME));
+        assertNotNull(new PfReferenceKey("ParentKeyName", VERSION001, LOCAL_NAME));
+        assertNotNull(new PfReferenceKey("ParentKeyName", VERSION001, PARENT_LOCAL_NAME, LOCAL_NAME));
+        assertNotNull(new PfReferenceKey("ParentKeyName:0.0.1:ParentLocalName:LocalName"));
+        assertEquals(PfReferenceKey.getNullKey().getKey(), PfReferenceKey.getNullKey());
+        assertEquals("NULL:0.0.0:NULL:NULL", PfReferenceKey.getNullKey().getId());
+
+        assertThatThrownBy(() -> new PfReferenceKey(new PfConceptKey(), null))
+            .hasMessage("parameter \"localName\" is null");
+    }
+
+    @Test
+    void testPfReferenceKey() {
+        PfReferenceKey testReferenceKey = new PfReferenceKey();
+        testReferenceKey.setParentConceptKey(new PfConceptKey("PN", VERSION001));
+        assertEquals("PN:0.0.1", testReferenceKey.getParentConceptKey().getId());
+
+        assertEquals(0, testReferenceKey.getMajorVersion());
+        assertEquals(0, testReferenceKey.getMinorVersion());
+        assertEquals(1, testReferenceKey.getPatchVersion());
+
+        assertEquals(1, testReferenceKey.getKeys().size());
+        assertFalse(testReferenceKey.isNullKey());
+
+        testReferenceKey.setParentReferenceKey(new PfReferenceKey("PN", VERSION001, "LN"));
+        assertEquals("PN:0.0.1:NULL:LN", testReferenceKey.getParentReferenceKey().getId());
+
+        testReferenceKey.setParentKeyName("NPKN");
+        assertEquals("NPKN", testReferenceKey.getParentKeyName());
+
+        testReferenceKey.setParentKeyVersion(VERSION001);
+        assertEquals(VERSION001, testReferenceKey.getParentKeyVersion());
+
+        testReferenceKey.setParentLocalName(NPKLN);
+        assertEquals(NPKLN, testReferenceKey.getParentLocalName());
+
+        testReferenceKey.setLocalName("NLN");
+        assertEquals("NLN", testReferenceKey.getLocalName());
+
+        assertThatThrownBy(() -> testReferenceKey.isCompatible(null))
+            .hasMessageMatching("^otherKey is marked .*on.*ull but is null$");
+
+        assertFalse(testReferenceKey.isCompatible(PfConceptKey.getNullKey()));
+        assertFalse(testReferenceKey.isCompatible(PfReferenceKey.getNullKey()));
+        assertTrue(testReferenceKey.isCompatible(testReferenceKey));
+
+        assertEquals(PfKey.Compatibility.DIFFERENT, testReferenceKey.getCompatibility(PfConceptKey.getNullKey()));
+        assertEquals(PfKey.Compatibility.DIFFERENT, testReferenceKey.getCompatibility(PfReferenceKey.getNullKey()));
+        assertEquals(PfKey.Compatibility.IDENTICAL, testReferenceKey.getCompatibility(testReferenceKey));
+
+        assertTrue(testReferenceKey.validate("").isValid());
+    }
+
+    @Test
+    void testMultiplePfReferenceKey() {
+        PfReferenceKey testReferenceKey = setTestReferenceKey();
+        testReferenceKey.clean();
+
+        PfReferenceKey clonedReferenceKey = new PfReferenceKey(testReferenceKey);
+        assertEquals("PfReferenceKey(parentKeyName=NPKN, parentKeyVersion=0.0.1, parentLocalName=NPKLN, localName=NLN)",
+            clonedReferenceKey.toString());
+
+        assertNotEquals(0, testReferenceKey.hashCode());
+
+        assertEquals(testReferenceKey, (Object) testReferenceKey);
+        assertEquals(testReferenceKey, clonedReferenceKey);
+        assertNotEquals(testReferenceKey, (Object) "Hello");
+        assertNotEquals(testReferenceKey, new PfReferenceKey("PKN", VERSION002, "PLN", "LN"));
+        assertNotEquals(testReferenceKey, new PfReferenceKey("NPKN", VERSION002, "PLN", "LN"));
+        assertNotEquals(testReferenceKey, new PfReferenceKey("NPKN", VERSION001, "PLN", "LN"));
+        assertNotEquals(testReferenceKey, new PfReferenceKey("NPKN", VERSION001, "NPLN", "LN"));
+        assertEquals(testReferenceKey, new PfReferenceKey("NPKN", VERSION001, NPKLN, "NLN"));
+
+        assertEquals(0, testReferenceKey.compareTo(testReferenceKey));
+        assertEquals(0, testReferenceKey.compareTo(clonedReferenceKey));
+        assertNotEquals(0, testReferenceKey.compareTo(new PfConceptKey()));
+        assertNotEquals(0, testReferenceKey.compareTo(new PfReferenceKey("PKN", VERSION002, "PLN", "LN")));
+        assertNotEquals(0, testReferenceKey.compareTo(new PfReferenceKey("NPKN", VERSION002, "PLN", "LN")));
+        assertNotEquals(0, testReferenceKey.compareTo(new PfReferenceKey("NPKN", VERSION001, "PLN", "LN")));
+        assertNotEquals(0, testReferenceKey.compareTo(new PfReferenceKey("NPKN", VERSION001, "NPLN", "LN")));
+        assertEquals(0, testReferenceKey.compareTo(new PfReferenceKey("NPKN", VERSION001, NPKLN, "NLN")));
+
+        assertNotNull(testReferenceKey);
+
+        assertThatThrownBy(() -> new PfReferenceKey((PfReferenceKey) null)).isInstanceOf(NullPointerException.class);
+
+        assertEquals(testReferenceKey, new PfReferenceKey(testReferenceKey));
+    }
+
+    @Test
+    void testValidation() throws Exception {
+        PfReferenceKey testReferenceKey = new PfReferenceKey();
+        testReferenceKey.setParentConceptKey(new PfConceptKey("PN", VERSION001));
+        assertEquals("PN:0.0.1", testReferenceKey.getParentConceptKey().getId());
+
+        Field parentNameField = testReferenceKey.getClass().getDeclaredField("parentKeyName");
+        parentNameField.setAccessible(true);
+        parentNameField.set(testReferenceKey, "Parent Name");
+        ValidationResult validationResult = testReferenceKey.validate("");
+        parentNameField.set(testReferenceKey, "ParentName");
+        parentNameField.setAccessible(false);
+        assertThat(validationResult.getResult()).contains("\"parentKeyName\"")
+                        .contains("does not match regular expression " + PfKey.NAME_REGEXP);
+
+        Field parentVersionField = testReferenceKey.getClass().getDeclaredField("parentKeyVersion");
+        parentVersionField.setAccessible(true);
+        parentVersionField.set(testReferenceKey, "Parent Version");
+        ValidationResult validationResult2 = testReferenceKey.validate("");
+        parentVersionField.set(testReferenceKey, VERSION001);
+        parentVersionField.setAccessible(false);
+        assertThat(validationResult2.getResult()).contains("\"parentKeyVersion\"")
+            .contains("does not match regular expression " + PfKey.VERSION_REGEXP);
+
+        Field parentLocalNameField = testReferenceKey.getClass().getDeclaredField("parentLocalName");
+        parentLocalNameField.setAccessible(true);
+        parentLocalNameField.set(testReferenceKey, "Parent Local Name");
+        ValidationResult validationResult3 = testReferenceKey.validate("");
+        parentLocalNameField.set(testReferenceKey, PARENT_LOCAL_NAME);
+        parentLocalNameField.setAccessible(false);
+        assertThat(validationResult3.getResult()).contains("\"parentLocalName\"")
+            .contains("does not match regular expression [A-Za-z0-9\\-_\\.]+|^$");
+
+        Field localNameField = testReferenceKey.getClass().getDeclaredField("localName");
+        localNameField.setAccessible(true);
+        localNameField.set(testReferenceKey, "Local Name");
+        ValidationResult validationResult4 = testReferenceKey.validate("");
+        localNameField.set(testReferenceKey, LOCAL_NAME);
+        localNameField.setAccessible(false);
+        assertThat(validationResult4.getResult()).contains("\"localName\"")
+        .contains("does not match regular expression [A-Za-z0-9\\-_\\.]+|^$");
+    }
+
+    private PfReferenceKey setTestReferenceKey() {
+        PfReferenceKey testReferenceKey = new PfReferenceKey();
+        testReferenceKey.setParentConceptKey(new PfConceptKey("PN", VERSION001));
+        testReferenceKey.setParentReferenceKey(new PfReferenceKey("PN", VERSION001, "LN"));
+        testReferenceKey.setParentKeyName("NPKN");
+        testReferenceKey.setParentKeyVersion(VERSION001);
+        testReferenceKey.setParentLocalName(NPKLN);
+        testReferenceKey.setLocalName("NLN");
+
+        return testReferenceKey;
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/base/PfUtilsTest.java b/policy-models/src/test/java/org/onap/policy/models/base/PfUtilsTest.java
new file mode 100644 (file)
index 0000000..9d142bf
--- /dev/null
@@ -0,0 +1,121 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019-2020, 2024 Nordix Foundation.
+ *  Modifications Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import lombok.Getter;
+import lombok.ToString;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Test the PfUtils class.
+ *
+ * @author Liam Fallon (liam.fallon@est.tech)
+ */
+class PfUtilsTest {
+
+    private static final String HELLO = "hello";
+
+    @Test
+    void testCompareObjects() {
+        assertEquals(0, PfUtils.compareObjects(null, null));
+        assertEquals(-1, PfUtils.compareObjects(HELLO, null));
+        assertEquals(1, PfUtils.compareObjects(null, HELLO));
+        assertNotEquals(0, PfUtils.compareObjects(HELLO, "goodbye"));
+        assertEquals(0, PfUtils.compareObjects(HELLO, HELLO));
+    }
+
+    @Test
+    void testMapList() {
+        List<Object> resultList = PfUtils.mapList(null, item -> {
+            throw new RuntimeException("should not be invoked");
+        });
+        assertNull(resultList);
+
+        List<String> origList = Arrays.asList("123", "456");
+        List<Integer> newList = PfUtils.mapList(origList, item -> Integer.valueOf(item) + 5);
+
+        assertEquals(Arrays.asList(128, 461), newList);
+
+        // verify that we can modify the list without throwing an exception
+        newList.remove(1);
+        newList.add(789);
+    }
+
+    @Test
+    void testMapMap() {
+        Map<String, String> resultMap = PfUtils.mapMap(null, item -> {
+            throw new RuntimeException("should not be invoked");
+        });
+        assertNull(resultMap);
+
+        Map<String, String> origMap = new TreeMap<>();
+        origMap.put("key2A", "123");
+        origMap.put("key2B", "456");
+        Map<String, Integer> newMap = PfUtils.mapMap(origMap, item -> Integer.valueOf(item) + 10);
+
+        assertEquals("{key2A=133, key2B=466}", newMap.toString());
+
+        // verify that we can modify the map without throwing an exception
+        newMap.remove("abcX");
+        newMap.put("something", 789);
+    }
+
+    @Test
+    void testMakeCopy() {
+        assertNull(PfUtils.makeCopy((MyObject) null));
+        NoCopyConstructor noCopyConstructor = new NoCopyConstructor();
+        MyObject origObject = new MyObject();
+        origObject.name = HELLO;
+        assertEquals(origObject.toString(), PfUtils.makeCopy(origObject).toString());
+
+        assertThatThrownBy(() -> PfUtils.makeCopy(noCopyConstructor)).isInstanceOf(PfModelRuntimeException.class);
+    }
+
+    @Getter
+    @ToString
+    private static class MyObject {
+        private String name;
+
+        public MyObject() {
+            // do nothing
+        }
+
+        @SuppressWarnings("unused")
+        public MyObject(MyObject source) {
+            this.name = source.name;
+        }
+    }
+
+    @Getter
+    private static class NoCopyConstructor {
+        private String name;
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/base/PfValidatorTest.java b/policy-models/src/test/java/org/onap/policy/models/base/PfValidatorTest.java
new file mode 100644 (file)
index 0000000..3787aef
--- /dev/null
@@ -0,0 +1,229 @@
+/*-
+ * ============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.PfMin;
+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 testVerPfMin() {
+        PfMinChecker data = new PfMinChecker();
+        data.intValue = 10;
+        assertThat(validator.validateTop("", data).getResult()).isNull();
+
+        data.intValue = -2;
+        assertThat(validator.validateTop("", data).getResult()).isNull();
+
+        data.intValue = null;
+        assertThat(validator.validateTop("", data).getResult()).isNull();
+
+        data.intValue = STRING_VALUE;
+        assertThat(validator.validateTop("", data).getResult()).isNull();
+
+        data.intValue = -1;
+        assertThat(validator.validateTop("", data).getResult()).contains("intValue", "-1");
+    }
+
+    @Test
+    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 PfMinChecker {
+        @Getter
+        @PfMin(value = 5, allowed = -2)
+        private Object intValue;
+    }
+
+    public static class CascadeChecker extends Validated {
+        @Getter
+        @Valid
+        private StdAnnotation plain;
+
+        @Override
+        public BeanValidationResult validate(@NonNull String fieldName) {
+            // directly validates "plain"
+            return new PfValidator().validateTop(fieldName, plain);
+        }
+    }
+
+    public static class FullKeyAnnot {
+        @Getter
+        @VerifyKey(keyNotNull = true, nameNotNull = true, versionNotNull = true, valid = true)
+        private Object key;
+    }
+
+    public static class EmptyKeyAnnot {
+        @Getter
+        @VerifyKey(keyNotNull = false, nameNotNull = false, versionNotNull = false, valid = false)
+        private PfKey key;
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/base/ValidatedTest.java b/policy-models/src/test/java/org/onap/policy/models/base/ValidatedTest.java
new file mode 100644 (file)
index 0000000..6d12614
--- /dev/null
@@ -0,0 +1,170 @@
+/*-
+ * ============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;
+        }
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/base/testconcepts/DummyAuthorativeConcept.java b/policy-models/src/test/java/org/onap/policy/models/base/testconcepts/DummyAuthorativeConcept.java
new file mode 100644 (file)
index 0000000..0734108
--- /dev/null
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base.testconcepts;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.onap.policy.models.base.PfNameVersion;
+
+/**
+ * Dummy authorative concept.
+ *
+ * @author Liam Fallon (liam.fallon@est.tech)
+ */
+@Data
+@NoArgsConstructor
+public class DummyAuthorativeConcept implements PfNameVersion {
+    private String name;
+    private String version;
+    private String description;
+
+    /**
+     * Constructor.
+     *
+     * @param name the name
+     * @param version the version
+     * @param description the description
+     */
+    public DummyAuthorativeConcept(final String name, final String version, final String description) {
+        this.name = name;
+        this.version = version;
+        this.description = description;
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/base/testconcepts/DummyPfConcept.java b/policy-models/src/test/java/org/onap/policy/models/base/testconcepts/DummyPfConcept.java
new file mode 100644 (file)
index 0000000..25a6cb7
--- /dev/null
@@ -0,0 +1,129 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019, 2023 Nordix Foundation.
+ *  Modifications Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base.testconcepts;
+
+import jakarta.persistence.EmbeddedId;
+import java.io.Serial;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NonNull;
+import org.apache.commons.lang3.ObjectUtils;
+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.PfConcept;
+import org.onap.policy.models.base.PfConceptKey;
+import org.onap.policy.models.base.PfKey;
+import org.onap.policy.models.base.validation.annotations.VerifyKey;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class DummyPfConcept extends PfConcept implements PfAuthorative<DummyAuthorativeConcept> {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    @EmbeddedId
+    @VerifyKey
+    @NotNull
+    private PfConceptKey key;
+
+    @NotBlank
+    private String description;
+
+
+    /**
+     * The Default Constructor creates a {@link DummyPfConcept} object with a null key.
+     */
+    public DummyPfConcept() {
+        this(new PfConceptKey());
+    }
+
+    /**
+     * The Key Constructor creates a {@link DummyPfConcept} object with the given concept key.
+     *
+     * @param key the key
+     */
+    public DummyPfConcept(@NonNull final PfConceptKey key) {
+        this.key = key;
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DummyPfConcept(final DummyPfConcept copyConcept) {
+        super(copyConcept);
+        this.key = new PfConceptKey(copyConcept.key);
+        this.description = copyConcept.description;
+    }
+
+    @Override
+    public DummyAuthorativeConcept toAuthorative() {
+        DummyAuthorativeConcept dac = new DummyAuthorativeConcept();
+        dac.setName(key.getName());
+        dac.setVersion(key.getVersion());
+        dac.setDescription(description);
+
+        return dac;
+    }
+
+    @Override
+    public void fromAuthorative(DummyAuthorativeConcept dac) {
+        key.setName(dac.getName());
+        key.setVersion(dac.getVersion());
+        description = dac.getDescription();
+    }
+
+    @Override
+    public List<PfKey> getKeys() {
+        return getKey().getKeys();
+    }
+
+    @Override
+    public void clean() {
+        key.clean();
+
+        description = (description != null ? description.trim() : null);
+    }
+
+    @Override
+    public int compareTo(final PfConcept otherConcept) {
+        if (otherConcept == null) {
+            return -1;
+        }
+        if (this == otherConcept) {
+            return 0;
+        }
+        if (getClass() != otherConcept.getClass()) {
+            return this.hashCode() - otherConcept.hashCode();
+        }
+
+        final DummyPfConcept other = (DummyPfConcept) otherConcept;
+        if (!key.equals(other.key)) {
+            return key.compareTo(other.key);
+        }
+
+        return ObjectUtils.compare(description, other.description);
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/base/testconcepts/DummyPfKey.java b/policy-models/src/test/java/org/onap/policy/models/base/testconcepts/DummyPfKey.java
new file mode 100644 (file)
index 0000000..4b3d9e8
--- /dev/null
@@ -0,0 +1,122 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019, 2023 Nordix Foundation.
+ *  Modifications Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base.testconcepts;
+
+import java.io.Serial;
+import java.util.List;
+import lombok.NonNull;
+import org.onap.policy.common.parameters.BeanValidationResult;
+import org.onap.policy.models.base.PfConcept;
+import org.onap.policy.models.base.PfKey;
+
+public class DummyPfKey extends PfKey {
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+    public DummyPfKey() {
+        // Default constructor
+    }
+
+    public DummyPfKey(DummyPfKey source) {
+        super(source);
+    }
+
+    @Override
+    public int compareTo(@NonNull PfConcept arg0) {
+        return 0;
+    }
+
+    @Override
+    public String getId() {
+        return null;
+    }
+
+    @Override
+    public boolean isNullKey() {
+        return false;
+    }
+
+    @Override
+    public Compatibility getCompatibility(@NonNull PfKey otherKey) {
+        return null;
+    }
+
+    @Override
+    public boolean isCompatible(@NonNull PfKey otherKey) {
+        return false;
+    }
+
+    @Override
+    public PfKey getKey() {
+        return null;
+    }
+
+    @Override
+    public List<PfKey> getKeys() {
+        return List.of(getKey());
+    }
+
+    @Override
+    public BeanValidationResult validate(@NonNull String fieldName) {
+        return null;
+    }
+
+    @Override
+    public void clean() {
+        // nothing to do
+    }
+
+    @Override
+    public boolean equals(Object otherObject) {
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return "";
+    }
+
+    @Override
+    public int hashCode() {
+        return 0;
+    }
+
+    @Override
+    public boolean isNewerThan(@NonNull PfKey otherKey) {
+        return false;
+    }
+
+    @Override
+    public int getMajorVersion() {
+        return 0;
+    }
+
+    @Override
+    public int getMinorVersion() {
+        return 0;
+    }
+
+    @Override
+    public int getPatchVersion() {
+        return 0;
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/base/testconcepts/DummyPfNameVersion.java b/policy-models/src/test/java/org/onap/policy/models/base/testconcepts/DummyPfNameVersion.java
new file mode 100644 (file)
index 0000000..1d28573
--- /dev/null
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ *  Modifications Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base.testconcepts;
+
+import lombok.Data;
+import org.onap.policy.models.base.PfNameVersion;
+
+/**
+ * Dummy implementation of the {@link PfNameVersion} interface.
+ *
+ * @author Liam Fallon (liam.fallon@est.tech)
+ */
+@Data
+public class DummyPfNameVersion implements PfNameVersion {
+    private String name;
+    private String version;
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/errors/concepts/ErrorResponseTest.java b/policy-models/src/test/java/org/onap/policy/models/errors/concepts/ErrorResponseTest.java
new file mode 100644 (file)
index 0000000..3ede12a
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Decision Models
+ * ================================================================================
+ * Copyright (C) 2019 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.errors.concepts;
+
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import jakarta.ws.rs.core.Response;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class ErrorResponseTest {
+
+    static final Logger logger = LoggerFactory.getLogger(ErrorResponseTest.class);
+
+    @Test
+    void test() {
+        assertThatCode(() -> {
+            ErrorResponse error = new ErrorResponse();
+
+            error.setResponseCode(Response.Status.NOT_ACCEPTABLE);
+            error.setErrorMessage("Missing metadata section");
+
+            error.setErrorDetails(List.of("You must have a metadata section with policy-id value"));
+
+            error.setWarningDetails(List.of("Please make sure topology template field is included."));
+
+            StandardCoder coder = new StandardCoder();
+            String jsonOutput = coder.encode(error);
+
+            logger.debug("Resulting json output {}", jsonOutput);
+
+            ErrorResponse deserializedResponse = coder.decode(jsonOutput, ErrorResponse.class);
+
+            assertEquals(deserializedResponse, error);
+        }).doesNotThrowAnyException();
+    }
+
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/errors/concepts/ErrorResponseUtilsTest.java b/policy-models/src/test/java/org/onap/policy/models/errors/concepts/ErrorResponseUtilsTest.java
new file mode 100644 (file)
index 0000000..317c42c
--- /dev/null
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019-2020, 2024 Nordix Foundation.
+ *  Modifications Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.errors.concepts;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.IOException;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Test the {@link ErrorResponseUtils} class.
+ *
+ * @author Liam Fallon (liam.fallon@est.tech)
+ */
+class ErrorResponseUtilsTest {
+    private static final String EXCEPTION1 = "Exception 1";
+
+    @Test
+    void testErrorResponseUtils() {
+        final IOException ioe = new IOException(EXCEPTION1, new NumberFormatException("Exception 0"));
+        final ErrorResponse errorResponse = new ErrorResponse();
+        assertThat(ioe).hasMessage(EXCEPTION1);
+
+        ErrorResponseUtils.getExceptionMessages(errorResponse, ioe);
+        assertEquals(EXCEPTION1, errorResponse.getErrorMessage());
+        assertEquals(EXCEPTION1, errorResponse.getErrorDetails().get(0));
+        assertEquals("Exception 0", errorResponse.getErrorDetails().get(1));
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/errors/concepts/TestModels.java b/policy-models/src/test/java/org/onap/policy/models/errors/concepts/TestModels.java
new file mode 100644 (file)
index 0000000..4914cc6
--- /dev/null
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Decision Models
+ * ================================================================================
+ * Copyright (C) 2019 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.errors.concepts;
+
+import com.openpojo.reflection.filters.FilterPackageInfo;
+import com.openpojo.validation.Validator;
+import com.openpojo.validation.ValidatorBuilder;
+import com.openpojo.validation.test.impl.GetterTester;
+import com.openpojo.validation.test.impl.SetterTester;
+import org.junit.jupiter.api.Test;
+import org.onap.policy.common.utils.test.ToStringTester;
+
+class TestModels {
+
+    @Test
+    void testDecisionModels() {
+        final Validator validator = ValidatorBuilder.create().with(new ToStringTester()).with(new SetterTester())
+                .with(new GetterTester()).build();
+        validator.validate(TestModels.class.getPackage().getName(), new FilterPackageInfo());
+    }
+
+
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/PojosTest.java b/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/PojosTest.java
new file mode 100644 (file)
index 0000000..1c73676
--- /dev/null
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2021-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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import com.openpojo.reflection.filters.FilterClassName;
+import com.openpojo.reflection.filters.FilterPackageInfo;
+import com.openpojo.validation.Validator;
+import com.openpojo.validation.ValidatorBuilder;
+import com.openpojo.validation.rule.impl.GetterMustExistRule;
+import com.openpojo.validation.rule.impl.SetterMustExistRule;
+import com.openpojo.validation.test.impl.GetterTester;
+import com.openpojo.validation.test.impl.SetterTester;
+import org.junit.jupiter.api.Test;
+import org.onap.policy.common.utils.test.ToStringTester;
+
+/**
+ * Class to perform unit tests of all pojos.
+ *
+ * @author Chenfei Gao (cgao@research.att.com)
+ *
+ */
+class PojosTest {
+
+    private static final String POJO_PACKAGE = "org.onap.policy.models.tosca.authorative.concepts";
+
+    @Test
+    void testPojos() {
+        // @formatter:off
+        final Validator validator = ValidatorBuilder
+                .create()
+                .with(new ToStringTester())
+                .with(new SetterMustExistRule())
+                .with(new GetterMustExistRule())
+                .with(new SetterTester())
+                .with(new GetterTester())
+                .build();
+        validator.validate(POJO_PACKAGE,
+                new FilterPackageInfo(),
+                new FilterClassName(ToscaIdentifierTestBase.class.getName()),
+                new FilterClassName(".*Test$")
+        );
+        // @formatter:on
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaCapabilityAssignmentTest.java b/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaCapabilityAssignmentTest.java
new file mode 100644 (file)
index 0000000..6a8f6ef
--- /dev/null
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.List;
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+
+class ToscaCapabilityAssignmentTest {
+
+    @Test
+    void testToscaCapabilityAssignmentCopyConstructor() {
+        ToscaCapabilityAssignment original = new ToscaCapabilityAssignment();
+        original.setAttributes(Map.of("key", "value"));
+        original.setOccurrences(List.of("occurrence"));
+
+        ToscaCapabilityAssignment copy = new ToscaCapabilityAssignment(original);
+
+        assertEquals(original.getAttributes(), copy.getAttributes());
+        assertEquals(original.getOccurrences(), copy.getOccurrences());
+    }
+
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaConceptIdentifierTest.java b/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaConceptIdentifierTest.java
new file mode 100644 (file)
index 0000000..17fbeef
--- /dev/null
@@ -0,0 +1,108 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Models
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2021, 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.tosca.authorative.concepts;
+
+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 static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+import org.onap.policy.common.parameters.ValidationResult;
+import org.onap.policy.models.base.PfConceptKey;
+
+/**
+ * Test methods not tested by {@link PojosTest}.
+ */
+class ToscaConceptIdentifierTest extends ToscaIdentifierTestBase<ToscaConceptIdentifier> {
+
+    public ToscaConceptIdentifierTest() {
+        super(ToscaConceptIdentifier.class, "name", "version");
+    }
+
+    @Test
+    void testAllArgsConstructor() {
+        assertThatThrownBy(() -> new ToscaConceptIdentifier(null, VERSION)).isInstanceOf(NullPointerException.class);
+        assertThatThrownBy(() -> new ToscaConceptIdentifier(NAME, null)).isInstanceOf(NullPointerException.class);
+
+        ToscaConceptIdentifier orig = new ToscaConceptIdentifier(NAME, VERSION);
+        assertEquals(NAME, orig.getName());
+        assertEquals(VERSION, orig.getVersion());
+    }
+
+    @Test
+    void testCopyConstructor() {
+        assertThatThrownBy(() -> new ToscaConceptIdentifier((ToscaConceptIdentifier) null))
+                .isInstanceOf(NullPointerException.class);
+
+        ToscaConceptIdentifier orig = new ToscaConceptIdentifier();
+
+        // verify with null values
+        assertEquals(orig.toString(), new ToscaConceptIdentifier(orig).toString());
+
+        // verify with all values
+        orig = new ToscaConceptIdentifier(NAME, VERSION);
+        assertEquals(orig.toString(), new ToscaConceptIdentifier(orig).toString());
+    }
+
+
+    @Test
+    void testPfKey() {
+        assertThatThrownBy(() -> new ToscaConceptIdentifier((PfConceptKey) null))
+                .isInstanceOf(NullPointerException.class);
+
+        PfConceptKey origKey = new PfConceptKey("Hello", "0.0.1");
+
+        assertEquals(origKey.getName(), new ToscaConceptIdentifier(origKey).getName());
+
+        assertEquals(origKey, new ToscaConceptIdentifier(origKey).asConceptKey());
+    }
+
+    @Test
+    void testValidatePapRest() throws Exception {
+        ToscaConceptIdentifier ident = new ToscaConceptIdentifier(NAME, VERSION);
+        ValidationResult result = ident.validatePapRest();
+        assertNotNull(result);
+        assertTrue(result.isValid());
+        assertNull(result.getResult());
+
+        ident = makeIdent(NAME, null);
+        result = ident.validatePapRest();
+        assertNotNull(result);
+        assertFalse(result.isValid());
+        assertNotNull(result.getResult());
+
+        ident = makeIdent(null, VERSION);
+        result = ident.validatePapRest();
+        assertNotNull(result);
+        assertFalse(result.isValid());
+        assertNotNull(result.getResult());
+    }
+
+    @Test
+    @Override
+    void testCompareTo() throws Exception {
+        super.testCompareTo();
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaIdentifierTestBase.java b/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaIdentifierTestBase.java
new file mode 100644 (file)
index 0000000..ebd3146
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Models
+ * ================================================================================
+ * Copyright (C) 2019-2020 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.tosca.authorative.concepts;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.onap.policy.common.utils.coder.Coder;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+
+/**
+ * Super class to test identity keys.
+ *
+ * @param <T> type of key being tested
+ */
+class ToscaIdentifierTestBase<T extends Comparable<T>> {
+    public static final String NAME = "my-name";
+    public static final String VERSION = "1.2.3";
+
+    private static final Coder coder = new StandardCoder();
+
+    private final Class<T> clazz;
+    private final String nameField;
+    private final String versionField;
+
+
+    /**
+     * Constructs the object.
+     *
+     * @param clazz the type of class being tested
+     * @param nameField name of the field containing the "name"
+     * @param versionField name of the field containing the "version"
+     */
+    public ToscaIdentifierTestBase(Class<T> clazz, String nameField, String versionField) {
+        this.clazz = clazz;
+        this.nameField = nameField;
+        this.versionField = versionField;
+    }
+
+    /**
+     * Tests the compareTo() method.
+     *
+     * @throws Exception if an error occurs
+     */
+    void testCompareTo() throws Exception {
+        T ident = makeIdent(NAME, VERSION);
+        assertEquals(0, ident.compareTo(ident));
+
+        assertTrue(ident.compareTo(null) > 0);
+
+        assertEquals(0, ident.compareTo(makeIdent(NAME, VERSION)));
+        assertTrue(ident.compareTo(makeIdent(NAME, null)) > 0);
+        assertTrue(ident.compareTo(makeIdent(null, VERSION)) > 0);
+        assertTrue(ident.compareTo(makeIdent(NAME, VERSION + "a")) < 0);
+        assertTrue(ident.compareTo(makeIdent(NAME + "a", VERSION)) < 0);
+
+        // name takes precedence over version
+        assertTrue(makeIdent(NAME, VERSION + "a").compareTo(makeIdent(NAME + "a", VERSION)) < 0);
+    }
+
+    /**
+     * Makes an identifier. Uses JSON which does no error checking.
+     *
+     * @param name name to put into the identifier
+     * @param version version to put into the identifier
+     * @return a new identifier
+     * @throws CoderException if the JSON cannot be decoded
+     */
+    public T makeIdent(String name, String version) throws CoderException {
+        StringBuilder bldr = new StringBuilder();
+        bldr.append("{");
+
+        if (name != null) {
+            bldr.append("'");
+            bldr.append(nameField);
+            bldr.append("':'");
+            bldr.append(name);
+            bldr.append("'");
+        }
+
+        if (version != null) {
+            if (name != null) {
+                bldr.append(',');
+            }
+
+            bldr.append("'");
+            bldr.append(versionField);
+            bldr.append("':'");
+            bldr.append(version);
+            bldr.append("'");
+        }
+
+        bldr.append("}");
+
+        String json = bldr.toString().replace('\'', '"');
+
+        return coder.decode(json, clazz);
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaNameVersionTest.java b/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaNameVersionTest.java
new file mode 100644 (file)
index 0000000..2efb326
--- /dev/null
@@ -0,0 +1,101 @@
+/*-
+ * ============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.models.tosca.authorative.concepts;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.onap.policy.models.base.PfConceptKey;
+import org.onap.policy.models.base.PfKey;
+
+class ToscaNameVersionTest {
+
+    private static final String MY_NAME = "MyName";
+    private static final String MY_VERSION = "1.2.3";
+
+    private ToscaNameVersion tosca;
+
+    @BeforeEach
+    void setUp() {
+        tosca = new ToscaNameVersion(MY_NAME, MY_VERSION);
+    }
+
+    @Test
+    void testToscaNameVersionPfKey() {
+        tosca = new ToscaNameVersion(new PfConceptKey(MY_NAME, MY_VERSION));
+        assertEquals(MY_NAME, tosca.getName());
+        assertEquals(MY_VERSION, tosca.getVersion());
+
+        assertThatThrownBy(() -> new ToscaNameVersion((PfKey) null)).isInstanceOf(NullPointerException.class)
+                        .hasMessageContaining("key").hasMessageContaining("is null");
+    }
+
+    @Test
+    void testToscaNameVersionToscaNameVersion() {
+        tosca = new ToscaNameVersion(tosca);
+        assertEquals(MY_NAME, tosca.getName());
+        assertEquals(MY_VERSION, tosca.getVersion());
+    }
+
+    @Test
+    void testAsConceptKey() {
+        assertEquals(new PfConceptKey(MY_NAME, MY_VERSION), tosca.asConceptKey());
+    }
+
+    @Test
+    void testCommonCompareTo() {
+        assertThat(tosca.commonCompareTo(tosca)).isZero();
+        assertThat(tosca.commonCompareTo(null)).isNotZero();
+        assertThat(tosca.commonCompareTo(new MyNameVersion(MY_NAME, MY_VERSION))).isNotZero();
+        assertThat(tosca.commonCompareTo(new ToscaNameVersion(tosca))).isZero();
+        assertThat(tosca.commonCompareTo(new ToscaNameVersion(MY_NAME, null))).isNotZero();
+        assertThat(tosca.commonCompareTo(new ToscaNameVersion(null, MY_VERSION))).isNotZero();
+    }
+
+    @Test
+    void testToString() {
+        assertEquals(MY_NAME + " " + MY_VERSION, tosca.toString());
+    }
+
+    @Test
+    void testToscaNameVersion() {
+        tosca = new ToscaNameVersion();
+        assertNull(tosca.getName());
+        assertNull(tosca.getVersion());
+    }
+
+    @Test
+    void testToscaNameVersionStringString() {
+        assertEquals(MY_NAME, tosca.getName());
+        assertEquals(MY_VERSION, tosca.getVersion());
+    }
+
+    private static class MyNameVersion extends ToscaNameVersion {
+        public MyNameVersion(String name, String version) {
+            super(name, version);
+        }
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaNodeTemplateTest.java b/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaNodeTemplateTest.java
new file mode 100644 (file)
index 0000000..58474b3
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Models
+ * ================================================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * 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.tosca.authorative.concepts;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import org.junit.jupiter.api.Test;
+
+class ToscaNodeTemplateTest {
+
+    @Test
+    void testToscaNodeTemplate() {
+        assertThatThrownBy(() -> {
+            new ToscaNodeTemplate(null);
+        }).hasMessageMatching("copyObject is marked .*on.*ull but is null");
+
+        assertNotNull(new ToscaNodeTemplate(new ToscaNodeTemplate()));
+
+        ToscaNodeTemplate origNt = new ToscaNodeTemplate();
+
+        assertEquals(origNt, new ToscaNodeTemplate(origNt));
+
+        origNt.setProperties(new HashMap<>());
+        origNt.setCapabilities(new HashMap<>());
+        origNt.setRequirements(new ArrayList<>());
+        assertEquals(origNt, new ToscaNodeTemplate(origNt));
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyTest.java b/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyTest.java
new file mode 100644 (file)
index 0000000..123ed93
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Models
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2020-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.tosca.authorative.concepts;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import java.util.LinkedHashMap;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests methods not tested by {@link PojosTest}.
+ */
+class ToscaPolicyTest {
+
+    @Test
+    void testGetIdentifier_testGetTypeIdentifier() {
+        assertThatThrownBy(() -> {
+            new ToscaPolicy(null);
+        }).hasMessageMatching("copyObject is marked .*on.*ull but is null");
+
+        ToscaPolicy policy = new ToscaPolicy();
+
+        policy.setName("my_name");
+        policy.setVersion("1.2.3");
+        policy.setType("my_type");
+        policy.setTypeVersion("3.2.1");
+
+        ToscaEntity te = new ToscaEntity();
+        assertNull(te.getType());
+        assertNull(te.getTypeVersion());
+
+        assertEquals("ToscaEntityKey(name=my_name, version=1.2.3)", policy.getKey().toString());
+        assertEquals(new ToscaConceptIdentifier("my_name", "1.2.3"), policy.getKey().asIdentifier());
+
+        ToscaConceptIdentifier ident = policy.getIdentifier();
+        assertEquals("my_name", ident.getName());
+        assertEquals("1.2.3", ident.getVersion());
+
+        ToscaConceptIdentifier type = policy.getTypeIdentifier();
+        assertEquals("my_type", type.getName());
+        assertEquals("3.2.1", type.getVersion());
+
+        ToscaPolicy clonedPolicy0 = new ToscaPolicy(policy);
+        assertEquals(0, new ToscaEntityComparator<ToscaPolicy>().compare(policy, clonedPolicy0));
+
+        policy.setProperties(new LinkedHashMap<String, Object>());
+        policy.getProperties().put("PropertyKey", "PropertyValue");
+        ToscaPolicy clonedPolicy1 = new ToscaPolicy(policy);
+        assertEquals(0, new ToscaEntityComparator<ToscaPolicy>().compare(policy, clonedPolicy1));
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyTypeTest.java b/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyTypeTest.java
new file mode 100644 (file)
index 0000000..148cf8a
--- /dev/null
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019-2021 Nordix Foundation.
+ *  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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.LinkedHashMap;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Test of the {@link ToscaPolicyType} class.
+ *
+ * @author Liam Fallon (liam.fallon@est.tech)
+ */
+class ToscaPolicyTypeTest {
+
+    @Test
+    void testToscaPolicyType() {
+        assertThatThrownBy(() -> {
+            new ToscaPolicyType(null);
+        }).hasMessageMatching("copyObject is marked .*on.*ull but is null");
+
+        ToscaPolicyType tpt = new ToscaPolicyType();
+        tpt.setName("AType");
+        tpt.setVersion("1.2.3");
+        tpt.setDerivedFrom("AParentType");
+        tpt.setDescription("Desc");
+
+        ToscaPolicyType clonedTpt0 = new ToscaPolicyType(tpt);
+        assertEquals(0, new ToscaEntityComparator<ToscaPolicyType>().compare(tpt, clonedTpt0));
+
+        tpt.setMetadata(new LinkedHashMap<>());
+        tpt.setProperties(new LinkedHashMap<>());
+
+        tpt.getMetadata().put("MetaKey0", "Metavalue 0");
+
+        ToscaProperty tp = new ToscaProperty();
+        tpt.getProperties().put("Property0", tp);
+
+        ToscaPolicyType clonedTpt1 = new ToscaPolicyType(tpt);
+        assertEquals(0, new ToscaEntityComparator<ToscaPolicyType>().compare(tpt, clonedTpt1));
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPropertyTest.java b/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPropertyTest.java
new file mode 100644 (file)
index 0000000..f962b2f
--- /dev/null
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+class ToscaPropertyTest {
+
+    @Test
+    void testStatusEnumValues() {
+        assertEquals("SUPPORTED", ToscaProperty.Status.SUPPORTED.name());
+        assertEquals("UNSUPPORTED", ToscaProperty.Status.UNSUPPORTED.name());
+        assertEquals("EXPERIMENTAL", ToscaProperty.Status.EXPERIMENTAL.name());
+        assertEquals("DEPRECATED", ToscaProperty.Status.DEPRECATED.name());
+    }
+
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaRequirementTest.java b/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaRequirementTest.java
new file mode 100644 (file)
index 0000000..283b48a
--- /dev/null
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.authorative.concepts;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.List;
+import org.junit.jupiter.api.Test;
+
+class ToscaRequirementTest {
+
+    @Test
+    void testCopyConstructor() {
+        // Create original object and populate fields
+        ToscaRequirement original = new ToscaRequirement();
+        original.setCapability("capabilityA");
+        original.setNode("nodeA");
+        original.setRelationship("relationshipA");
+        original.setOccurrences(List.of("occurrence1", "occurrence2"));
+
+        // Use copy constructor
+        ToscaRequirement copy = new ToscaRequirement(original);
+
+        // Validate copied values
+        assertEquals(original.getCapability(), copy.getCapability());
+        assertEquals(original.getNode(), copy.getNode());
+        assertEquals(original.getRelationship(), copy.getRelationship());
+        assertEquals(original.getOccurrences(), copy.getOccurrences());
+    }
+
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaServiceTemplateTest.java b/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaServiceTemplateTest.java
new file mode 100644 (file)
index 0000000..b11b8a6
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Models
+ * ================================================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * 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.tosca.authorative.concepts;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.util.HashMap;
+import org.junit.jupiter.api.Test;
+
+class ToscaServiceTemplateTest {
+
+    @Test
+    void testToscServiceTemplate() {
+        assertThatThrownBy(() -> {
+            new ToscaServiceTemplate(null);
+        }).hasMessageMatching("copyObject is marked .*on.*ull but is null");
+
+        assertNotNull(new ToscaServiceTemplate(new ToscaServiceTemplate()));
+
+        ToscaServiceTemplate origSt = new ToscaServiceTemplate();
+
+        assertEquals(origSt, new ToscaServiceTemplate(origSt));
+
+        origSt.setCapabilityTypes(new HashMap<>());
+        origSt.setDataTypes(new HashMap<>());
+        origSt.setNodeTypes(new HashMap<>());
+        origSt.setPolicyTypes(new HashMap<>());
+        origSt.setRelationshipTypes(new HashMap<>());
+        origSt.setToscaTopologyTemplate(new ToscaTopologyTemplate());
+        assertEquals(origSt, new ToscaServiceTemplate(origSt));
+
+        assertEquals(origSt.getDataTypesAsMap(), new ToscaServiceTemplate(origSt).getDataTypesAsMap());
+        assertEquals(origSt.getPolicyTypesAsMap(), new ToscaServiceTemplate(origSt).getPolicyTypesAsMap());
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaTopologyTemplateTest.java b/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaTopologyTemplateTest.java
new file mode 100644 (file)
index 0000000..398dfb1
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Models
+ * ================================================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * 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.tosca.authorative.concepts;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import org.junit.jupiter.api.Test;
+
+class ToscaTopologyTemplateTest {
+
+    @Test
+    void testToscTopologyTemplate() {
+        assertThatThrownBy(() -> {
+            new ToscaTopologyTemplate(null);
+        }).hasMessageMatching("copyObject is marked .*on.*ull but is null");
+
+        assertNotNull(new ToscaTopologyTemplate(new ToscaTopologyTemplate()));
+
+        ToscaTopologyTemplate origTt = new ToscaTopologyTemplate();
+
+        assertEquals(origTt, new ToscaTopologyTemplate(origTt));
+
+        origTt.setDescription("A Description");
+        origTt.setInputs(new HashMap<>());
+        origTt.setNodeTemplates(new HashMap<>());
+        origTt.setPolicies(new ArrayList<>());
+        assertEquals(origTt, new ToscaTopologyTemplate(origTt));
+
+        assertEquals(origTt.getPoliciesAsMap(), new ToscaTopologyTemplate(origTt).getPoliciesAsMap());
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaWithToscaPropertiesTest.java b/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaWithToscaPropertiesTest.java
new file mode 100644 (file)
index 0000000..5fd391a
--- /dev/null
@@ -0,0 +1,52 @@
+/*-
+ * ============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.models.tosca.authorative.concepts;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+
+class ToscaWithToscaPropertiesTest {
+
+    @Test
+    void test() {
+        ToscaProperty prop1 = new ToscaProperty();
+        prop1.setDescription("description A");
+
+        ToscaProperty prop2 = new ToscaProperty();
+        prop2.setDescription("description B");
+
+        ToscaWithToscaProperties tosca = new ToscaWithToscaProperties();
+        assertEquals(tosca, new ToscaWithToscaProperties(tosca));
+
+        tosca.setProperties(Map.of("abc", prop1, "def", prop2));
+        assertEquals(tosca, new ToscaWithToscaProperties(tosca));
+
+        assertNotEquals(tosca, new ToscaWithToscaProperties());
+
+        assertThatThrownBy(() -> new ToscaWithToscaProperties(null)).hasMessageContaining("copyObject")
+                        .hasMessageContaining("is null");
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaWithTypeAndObjectPropertiesTest.java b/policy-models/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaWithTypeAndObjectPropertiesTest.java
new file mode 100644 (file)
index 0000000..9c9d5ba
--- /dev/null
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * Modifications Copyright (C) 2021, 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.tosca.authorative.concepts;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+
+class ToscaWithTypeAndObjectPropertiesTest {
+
+    @Test
+    void testCopyConstructor() {
+        ToscaWithTypeAndObjectProperties tosca = new ToscaWithTypeAndObjectProperties();
+        assertEquals(tosca, new ToscaWithTypeAndObjectProperties(tosca));
+
+        tosca.setProperties(Map.of("abc", 10, "def", "world"));
+        assertEquals(tosca, new ToscaWithTypeAndObjectProperties(tosca));
+
+        assertNotEquals(tosca, new ToscaWithTypeAndObjectProperties());
+
+        assertThatThrownBy(() -> new ToscaWithTypeAndObjectProperties(null)).hasMessageContaining("copyObject")
+                        .hasMessageContaining("is null");
+    }
+}
diff --git a/policy-models/src/test/java/org/onap/policy/models/tosca/utils/ToscaUtilsTest.java b/policy-models/src/test/java/org/onap/policy/models/tosca/utils/ToscaUtilsTest.java
new file mode 100644 (file)
index 0000000..65b7d60
--- /dev/null
@@ -0,0 +1,41 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019-2025 OpenInfra Foundation Europe. All rights reserved.
+ *  Modifications Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.tosca.utils;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
+import org.onap.policy.models.base.PfConceptKey;
+import org.onap.policy.models.base.PfKey;
+
+/**
+ * Import the {@link ToscaUtils} class.
+ *
+ * @author Liam Fallon (liam.fallon@est.tech)
+ */
+class ToscaUtilsTest {
+
+    @Test
+    void testGetPredefinedDataTypes() {
+        assertTrue(ToscaUtils.getPredefinedDataTypes().contains(new PfConceptKey("string", PfKey.NULL_KEY_VERSION)));
+    }
+}
diff --git a/pom.xml b/pom.xml
index 7e94ce7..51d02a3 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -37,6 +37,7 @@
         This is the root Maven module for the policy-clamp project.
 
         It contains the following modules:
+        - policy-models: dependency code previously in policy/models repo
         - policy-clamp-common: Common code for all Policy/CLAMP modules
         - policy-clamp-models: POJOs and other model code for REST and Kafka messages and for persistence
         - policy-clamp-runtime: The runtime server for CLAMP
@@ -56,6 +57,7 @@
         <policy.models.version>5.0.0-SNAPSHOT</policy.models.version>
     </properties>
     <modules>
+        <module>policy-models</module>
         <module>common</module>
         <module>examples</module>
         <module>models</module>
index 72dde04..6bc856b 100644 (file)
             <artifactId>utils</artifactId>
             <version>${policy.common.version}</version>
         </dependency>
-        <dependency>
-            <groupId>org.onap.policy.models</groupId>
-            <artifactId>policy-models-base</artifactId>
-            <version>${policy.models.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.onap.policy.models</groupId>
-            <artifactId>policy-models-errors</artifactId>
-            <version>${policy.models.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.onap.policy.models</groupId>
-            <artifactId>policy-models-tosca</artifactId>
-            <version>${policy.models.version}</version>
-        </dependency>
         <dependency>
             <groupId>com.google.code.gson</groupId>
             <artifactId>gson</artifactId>
             <groupId>org.openapitools</groupId>
             <artifactId>jackson-databind-nullable</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+            <scope>runtime</scope>
+        </dependency>
         <dependency>
             <groupId>jakarta.servlet</groupId>
             <artifactId>jakarta.servlet-api</artifactId>