Add model to save ToscaServiceTemplate as Json in ACM 22/132422/1
authorFrancescoFioraEst <francesco.fiora@est.tech>
Wed, 23 Nov 2022 10:04:55 +0000 (10:04 +0000)
committerFrancescoFioraEst <francesco.fiora@est.tech>
Wed, 23 Nov 2022 14:30:51 +0000 (14:30 +0000)
Issue-ID: POLICY-4462
Change-Id: I81a5a8922b0e980143a8da4b6d0572767620fb36
Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
22 files changed:
models/src/main/java/org/onap/policy/clamp/models/acm/document/base/DocConceptKey.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/base/DocUtil.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/base/ToscaServiceTemplateValidation.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaCapabilityAssignment.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaCapabilityType.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaConstraint.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaDataType.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaEntity.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaNodeTemplate.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaNodeType.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaParameter.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaPolicy.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaPolicyType.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaProperty.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaRelationshipType.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaRequirement.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaSchemaDefinition.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaServiceTemplate.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaTopologyTemplate.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaWithToscaProperties.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaWithTypeAndStringProperties.java [new file with mode: 0644]
models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/StringToServiceTemplateConverter.java [new file with mode: 0644]

diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/base/DocConceptKey.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/base/DocConceptKey.java
new file mode 100644 (file)
index 0000000..56413d8
--- /dev/null
@@ -0,0 +1,94 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.base;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NonNull;
+import lombok.ToString;
+import org.onap.policy.common.parameters.annotations.Pattern;
+import org.onap.policy.common.utils.validation.Assertions;
+import org.onap.policy.models.base.PfConceptKey;
+import org.onap.policy.models.base.PfKeyImpl;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@ToString
+public class DocConceptKey extends PfKeyImpl {
+
+    private static final long serialVersionUID = 1L;
+
+    @Pattern(regexp = NAME_REGEXP)
+    private String name;
+
+    @Pattern(regexp = VERSION_REGEXP)
+    private String version;
+
+    /**
+     * Constructor.
+     */
+    public DocConceptKey() {
+        this(NULL_KEY_NAME, NULL_KEY_VERSION);
+    }
+
+    @Override
+    public String getId() {
+        return name + ":" + version;
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocConceptKey(final PfConceptKey copyConcept) {
+        super(copyConcept);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocConceptKey(final DocConceptKey copyConcept) {
+        this(copyConcept.getName(), copyConcept.getVersion());
+    }
+
+    /**
+     * Temporary Constructor to create a key with the specified name and version.
+     *
+     * @param name the key name
+     * @param version the key version
+     */
+    public DocConceptKey(final String name, final String version) {
+        super(name, version);
+    }
+
+    @Override
+    public void setName(@NonNull final String name) {
+        this.name = Assertions.validateStringParameter(NAME_TOKEN, name, getNameRegEx());
+    }
+
+    @Override
+    public void setVersion(@NonNull final String version) {
+        this.version = Assertions.validateStringParameter(VERSION_TOKEN, version, getVersionRegEx());
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/base/DocUtil.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/base/DocUtil.java
new file mode 100644 (file)
index 0000000..5e31ad2
--- /dev/null
@@ -0,0 +1,320 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.base;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.function.Function;
+import javax.ws.rs.core.Response;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.policy.clamp.models.acm.document.concepts.DocToscaEntity;
+import org.onap.policy.clamp.models.acm.document.concepts.DocToscaServiceTemplate;
+import org.onap.policy.models.base.PfConceptKey;
+import org.onap.policy.models.base.PfKey;
+import org.onap.policy.models.base.PfModelRuntimeException;
+import org.onap.policy.models.base.PfNameVersion;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaEntity;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class DocUtil {
+
+    public static final String REF_DATA_TYPES = "dataTypes";
+    public static final String REF_POLICY_TYPES = "policyTypes";
+    public static final String REF_NODE_TYPES = "nodeTypes";
+    public static final String REF_CAPABILITY_TYPES = "capabilityTypes";
+    public static final String REF_RELATIONSHIP_TYPES = "relationshipTypes";
+    public static final String REF_NODE_TEMPLATES = "nodeTemplates";
+    public static final String REF_POLICIES = "policies";
+    public static final String REF_REQUIREMENTS = "requirements";
+    public static final String REF_CAPABILITIES = "capabilities";
+
+    /**
+     * Convenience method to apply a mapping function to all of 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 of the items in the original map
+     */
+    public static <A extends PfNameVersion, R> Map<String, R> docMapToMap(Map<String, A> source,
+            Function<A, R> mapFunc) {
+        return docMapToMap(source, mapFunc, null);
+    }
+
+    /**
+     * Convenience method to apply a mapping function to all of 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 if source is null
+     * @return a new map, containing mappings of all of the items in the original map
+     */
+    public static <A extends PfNameVersion, R> Map<String, R> docMapToMap(Map<String, A> source, Function<A, R> mapFunc,
+            Map<String, R> defaultValue) {
+        if (source == null) {
+            return defaultValue;
+        }
+        Map<String, R> map = new LinkedHashMap<>();
+        for (Entry<String, A> ent : source.entrySet()) {
+            map.put(ent.getValue().getName(), mapFunc.apply(ent.getValue()));
+        }
+
+        return map;
+    }
+
+    /**
+     * Convenience method to apply a mapping function to all of 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 of the items in the original map, or {@code null} if the source is
+     *         {@code null}
+     */
+    public static <A extends ToscaEntity, R> Map<String, R> mapToDocMap(Map<String, A> source, Function<A, R> mapFunc) {
+        return mapToDocMap(source, mapFunc, null);
+    }
+
+    /**
+     * Convenience method to apply a mapping function to all of 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 if source is null
+     * @return a new map, containing mappings of all of the items in the original map, or defaultValue if the source is
+     *         {@code null}
+     */
+    public static <A extends ToscaEntity, R> Map<String, R> mapToDocMap(Map<String, A> source, Function<A, R> mapFunc,
+            Map<String, R> defaultValue) {
+        if (source == null) {
+            return defaultValue;
+        }
+        Map<String, R> conceptMap = new LinkedHashMap<>();
+
+        for (var incomingConceptEntry : source.entrySet()) {
+
+            var conceptKey = new PfConceptKey();
+            conceptKey.setName(incomingConceptEntry.getKey());
+            if (incomingConceptEntry.getValue().getVersion() != null) {
+                conceptKey.setVersion(incomingConceptEntry.getValue().getVersion());
+            }
+
+            incomingConceptEntry.getValue().setName(findConceptField(conceptKey, conceptKey.getName(),
+                    incomingConceptEntry.getValue(), PfNameVersion::getDefinedName));
+            incomingConceptEntry.getValue().setVersion(findConceptField(conceptKey, conceptKey.getVersion(),
+                    incomingConceptEntry.getValue(), PfNameVersion::getDefinedVersion));
+
+            var authoritiveImpl = mapFunc.apply(incomingConceptEntry.getValue());
+
+            // After all that, save the map entry
+            conceptMap.put(conceptKey.getId(), authoritiveImpl);
+        }
+
+        return conceptMap;
+    }
+
+    private static String findConceptField(final PfConceptKey conceptKey, final String keyFieldValue,
+            final PfNameVersion concept, final Function<PfNameVersion, String> fieldGetterFunction) {
+
+        String conceptField = fieldGetterFunction.apply(concept);
+
+        if (StringUtils.isBlank(conceptField) || keyFieldValue.equals(conceptField)) {
+            return keyFieldValue;
+        } else {
+            throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, "Key " + conceptKey.getId() + " field "
+                    + keyFieldValue + " does not match the value " + conceptField + " in the concept field");
+        }
+    }
+
+    /**
+     * Convenience method to apply a mapping function to all of the values of a list of maps, generating a new map.
+     *
+     * @param source list of maps whose values are to be mapped, or {@code null}
+     * @param mapFunc mapping function
+     * @return a new map, containing mappings of all of the items in the original map, or {@code null} if the source is
+     *         {@code null}
+     */
+    public static <A extends ToscaEntity, R> Map<String, R> listToDocMap(List<Map<String, A>> source,
+            Function<A, R> mapFunc) {
+
+        return listToDocMap(source, mapFunc, null);
+    }
+
+    /**
+     * Convenience method to apply a mapping function to all of the values of a list of maps, generating a new map.
+     *
+     * @param source list of maps whose values are to be mapped, or {@code null}
+     * @param mapFunc mapping function
+     * @param defaultValue if source is null
+     * @return a new map, containing mappings of all of the items in the original map, or defaultValue if the source is
+     *         {@code null}
+     */
+    public static <A extends ToscaEntity, R> Map<String, R> listToDocMap(List<Map<String, A>> source,
+            Function<A, R> mapFunc, Map<String, R> defaultValue) {
+        if (source == null) {
+            return defaultValue;
+        }
+        Map<String, R> conceptMap = new LinkedHashMap<>();
+
+        for (var map : source) {
+            conceptMap.putAll(mapToDocMap(map, mapFunc));
+        }
+
+        return conceptMap;
+    }
+
+    /**
+     * Convenience method to apply a mapping function to all of the values of a map, generating a new list of maps.
+     *
+     * @param source map whose values are to be mapped, or {@code null}
+     * @param mapFunc mapping function
+     * @return a new list of maps, containing mappings of all of the items in the original map, or {@code null} if the
+     *         source is {@code null}
+     */
+    public static <A extends PfNameVersion, R> List<Map<String, R>> docMapToList(Map<String, A> source,
+            Function<A, R> mapFunc) {
+        return docMapToList(source, mapFunc, null);
+    }
+
+    /**
+     * Convenience method to apply a mapping function to all of the values of a map, generating a new list of maps.
+     *
+     * @param source map whose values are to be mapped, or {@code null}
+     * @param mapFunc mapping function
+     * @param defaultValue if source is null
+     * @return a new list of maps, containing mappings of all of the items in the original map, or defaultValue if the
+     *         source is {@code null}
+     */
+    public static <A extends PfNameVersion, R> List<Map<String, R>> docMapToList(Map<String, A> source,
+            Function<A, R> mapFunc, List<Map<String, R>> defaultValue) {
+        if (source == null) {
+            return defaultValue;
+        }
+
+        List<Map<String, R>> result = new ArrayList<>();
+        for (Entry<String, A> ent : source.entrySet()) {
+            Map<String, R> map = new LinkedHashMap<>();
+            map.put(ent.getValue().getName(), mapFunc.apply(ent.getValue()));
+            result.add(map);
+
+        }
+
+        return result;
+    }
+
+    /**
+     * Create DocConceptKey.
+     *
+     * @param name the name
+     * @param version the version
+     * @return DocConceptKey
+     */
+    public static DocConceptKey createDocConceptKey(String name, String version) {
+        var key = new DocConceptKey();
+        if (version != null && !version.isBlank()) {
+            key.setName(name);
+            key.setVersion(version);
+        } else {
+            var list = name.split(":");
+            switch (list.length) {
+                case 0:
+                case 1:
+                    key.setName(name);
+                    key.setVersion(PfKey.NULL_KEY_VERSION);
+                    break;
+                case 2:
+                    key.setName(list[0]);
+                    key.setVersion(list[1]);
+                    break;
+                default:
+            }
+        }
+        return key;
+    }
+
+    /**
+     * Get DocToscaReferences.
+     *
+     * @return ToscaReferenceType
+     */
+    public static Map<String, Set<String>> getToscaReferences(DocToscaServiceTemplate serviceTemplate) {
+        var referenceType = new HashMap<String, Set<String>>();
+        fillReferenceType(referenceType, REF_DATA_TYPES, serviceTemplate.getDataTypes());
+        fillReferenceType(referenceType, REF_POLICY_TYPES, serviceTemplate.getPolicyTypes());
+        fillReferenceType(referenceType, REF_NODE_TYPES, serviceTemplate.getNodeTypes());
+        fillReferenceType(referenceType, REF_CAPABILITY_TYPES, serviceTemplate.getCapabilityTypes());
+        fillReferenceType(referenceType, REF_RELATIONSHIP_TYPES, serviceTemplate.getRelationshipTypes());
+
+        if (serviceTemplate.getNodeTypes() != null) {
+
+            serviceTemplate.getNodeTypes().values().forEach(
+                    nodeType -> fillReferenceType(referenceType, REF_REQUIREMENTS, nodeType.getRequirements()));
+        }
+        if (serviceTemplate.getToscaTopologyTemplate() != null) {
+
+            fillReferenceType(referenceType, REF_NODE_TEMPLATES,
+                    serviceTemplate.getToscaTopologyTemplate().getNodeTemplates());
+
+            fillReferenceType(referenceType, REF_POLICIES, serviceTemplate.getToscaTopologyTemplate().getPolicies());
+
+            if (serviceTemplate.getToscaTopologyTemplate().getNodeTemplates() != null) {
+                for (var nodeTemplate : serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().values()) {
+                    fillReferenceType(referenceType, REF_REQUIREMENTS, nodeTemplate.getRequirements());
+                    fillReferenceType(referenceType, REF_CAPABILITIES, nodeTemplate.getCapabilities());
+                }
+            }
+
+        }
+        return referenceType;
+    }
+
+    private static <A extends DocToscaEntity<?>> void fillReferenceType(Map<String, Set<String>> referenceType,
+            String type, Map<String, A> map) {
+        referenceType.putIfAbsent(type, new HashSet<>());
+        if (map != null) {
+            referenceType.get(type).addAll(toSetToscaReferences(map));
+        }
+
+    }
+
+    private static <A extends DocToscaEntity<?>> void fillReferenceType(Map<String, Set<String>> referenceType,
+            String type, List<Map<String, A>> list) {
+        referenceType.putIfAbsent(type, new HashSet<>());
+        if (list != null) {
+            list.forEach(map -> referenceType.get(type).addAll(toSetToscaReferences(map)));
+        }
+    }
+
+    private static <A extends DocToscaEntity<?>> Set<String> toSetToscaReferences(Map<String, A> map) {
+        Set<String> result = new HashSet<>();
+        for (var entity : map.values()) {
+            result.add(entity.getDocConceptKey().getId()); // ref for type
+            result.add(entity.getDocConceptKey().getName()); // ref for derived from
+        }
+        return result;
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/base/ToscaServiceTemplateValidation.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/base/ToscaServiceTemplateValidation.java
new file mode 100644 (file)
index 0000000..7649678
--- /dev/null
@@ -0,0 +1,233 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.base;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import org.onap.policy.clamp.models.acm.document.concepts.DocToscaEntity;
+import org.onap.policy.clamp.models.acm.document.concepts.DocToscaServiceTemplate;
+import org.onap.policy.common.parameters.BeanValidationResult;
+import org.onap.policy.common.parameters.ValidationStatus;
+import org.onap.policy.models.base.Validated;
+
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class ToscaServiceTemplateValidation {
+
+    private static final String ROOT_KEY_NAME_SUFFIX = ".Root";
+
+    /**
+     * validate a serviceTemplate.
+     *
+     * @param result the result
+     * @param serviceTemplate the serviceTemplate to validate
+     */
+    public static void validate(final BeanValidationResult result, DocToscaServiceTemplate serviceTemplate) {
+
+        var references = DocUtil.getToscaReferences(serviceTemplate);
+
+        validEntityTypeAncestors(serviceTemplate.getDataTypes(), references.get(DocUtil.REF_DATA_TYPES), result);
+        validEntityTypeAncestors(serviceTemplate.getCapabilityTypes(), references.get(DocUtil.REF_CAPABILITY_TYPES),
+                result);
+        validEntityTypeAncestors(serviceTemplate.getNodeTypes(), references.get(DocUtil.REF_NODE_TYPES), result);
+        validEntityTypeAncestors(serviceTemplate.getRelationshipTypes(), references.get(DocUtil.REF_RELATIONSHIP_TYPES),
+                result);
+        validEntityTypeAncestors(serviceTemplate.getPolicyTypes(), references.get(DocUtil.REF_POLICY_TYPES), result);
+
+        if (serviceTemplate.getNodeTypes() != null) {
+            for (var nodeType : serviceTemplate.getNodeTypes().values()) {
+                validEntityTypeAncestors(nodeType.getRequirements(), references.get(DocUtil.REF_REQUIREMENTS), result);
+            }
+        }
+
+        if (serviceTemplate.getToscaTopologyTemplate() != null) {
+            validEntityTypeAncestors(serviceTemplate.getToscaTopologyTemplate().getNodeTemplates(),
+                    references.get(DocUtil.REF_NODE_TEMPLATES), result);
+            validEntityTypeAncestors(serviceTemplate.getToscaTopologyTemplate().getPolicies(),
+                    references.get(DocUtil.REF_POLICIES), result);
+
+            if (serviceTemplate.getToscaTopologyTemplate().getNodeTemplates() != null) {
+                for (var nodeTemplate : serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().values()) {
+                    validEntityTypeAncestors(nodeTemplate.getCapabilities(), references.get(DocUtil.REF_CAPABILITIES),
+                            result);
+                    validEntityTypeAncestors(nodeTemplate.getRequirements(), references.get(DocUtil.REF_REQUIREMENTS),
+                            result);
+                }
+            }
+        }
+
+        validateReferencedDataTypes(result, serviceTemplate, references);
+
+        validatePolicyTypesInPolicies(result, serviceTemplate, references);
+
+    }
+
+    /**
+     * Validate that all data types referenced in policy types exist.
+     *
+     * @param result where the results are added
+     */
+    private static void validateReferencedDataTypes(final BeanValidationResult result,
+            DocToscaServiceTemplate serviceTemplate, Map<String, Set<String>> references) {
+        if (serviceTemplate.getDataTypes() != null) {
+            for (var dataType : serviceTemplate.getDataTypes().values()) {
+                validateReferencedDataTypesExists(result, dataType.getReferencedDataTypes(), references);
+            }
+        }
+
+        if (serviceTemplate.getPolicyTypes() != null) {
+            for (var policyType : serviceTemplate.getPolicyTypes().values()) {
+                validateReferencedDataTypesExists(result, policyType.getReferencedDataTypes(), references);
+            }
+        }
+        if (serviceTemplate.getNodeTypes() != null) {
+            for (var nodeType : serviceTemplate.getNodeTypes().values()) {
+                validateReferencedDataTypesExists(result, nodeType.getReferencedDataTypes(), references);
+            }
+        }
+    }
+
+    /**
+     * Validate that the referenced data types exist for a collection of data type keys.
+     *
+     * @param dataTypeKeyCollection the data type key collection
+     * @param result where the results are added
+     */
+    private static void validateReferencedDataTypesExists(final BeanValidationResult result,
+            final Collection<DocConceptKey> dataTypeKeyCollection, Map<String, Set<String>> references) {
+        for (DocConceptKey dataTypeKey : dataTypeKeyCollection) {
+            if (!isTypePresent(dataTypeKey, references.get(DocUtil.REF_DATA_TYPES))) {
+                result.addResult("data type", dataTypeKey.getId(), ValidationStatus.INVALID, Validated.NOT_FOUND);
+            }
+        }
+    }
+
+    /**
+     * Validate that all policy types referenced in policies exist.
+     *
+     * @param result where the results are added
+     */
+    private static void validatePolicyTypesInPolicies(final BeanValidationResult result,
+            DocToscaServiceTemplate serviceTemplate, Map<String, Set<String>> references) {
+        if (serviceTemplate.getToscaTopologyTemplate() == null) {
+            return;
+        }
+
+        if (serviceTemplate.getToscaTopologyTemplate().getPolicies() != null) {
+            for (var policy : serviceTemplate.getToscaTopologyTemplate().getPolicies().values()) {
+                var key = policy.getTypeDocConceptKey();
+                if (!isTypePresent(key, references.get(DocUtil.REF_POLICY_TYPES))) {
+                    result.addResult("policy type", key, ValidationStatus.INVALID, Validated.NOT_FOUND);
+                }
+            }
+        }
+        if (serviceTemplate.getToscaTopologyTemplate().getNodeTemplates() != null) {
+            for (var nodeTemplate : serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().values()) {
+                var key = nodeTemplate.getTypeDocConceptKey();
+                if (!isTypePresent(key, references.get(DocUtil.REF_NODE_TYPES))) {
+                    result.addResult("node Template", key, ValidationStatus.INVALID, Validated.NOT_FOUND);
+                }
+            }
+        }
+    }
+
+    private static boolean isTypePresent(String key, Set<String> reference) {
+        if (reference == null || reference.isEmpty()) {
+            return false;
+        }
+        return reference.contains(key);
+    }
+
+    private static boolean isTypePresent(DocConceptKey key, Set<String> reference) {
+        if (reference == null || reference.isEmpty()) {
+            return false;
+        }
+        return reference.contains(key.getId());
+    }
+
+    private static String extractDerivedFrom(DocToscaEntity<?> entityType, final BeanValidationResult result) {
+        if (entityType.getDerivedFrom() == null) {
+            return null;
+        }
+        var parentEntityTypeKey = entityType.getDerivedFrom();
+
+        if (parentEntityTypeKey.endsWith(ROOT_KEY_NAME_SUFFIX)) {
+            return null;
+        }
+        if (entityType.getName().equals(parentEntityTypeKey)) {
+            result.addResult("entity type", entityType.getDocConceptKey().getId(), ValidationStatus.INVALID,
+                    "ancestor of itself");
+            return null;
+        }
+        return parentEntityTypeKey;
+    }
+
+    /**
+     * validate all the ancestors of an entity type.
+     *
+     * @param entityTypes the set of entity types that exist
+     * @param result the result of the ancestor search with any warnings or errors
+     */
+    private static void validEntityTypeAncestors(Map<String, ? extends DocToscaEntity<?>> entityTypes,
+            Set<String> reference, @NonNull final BeanValidationResult result) {
+        if (entityTypes != null) {
+            for (var entityType : entityTypes.values()) {
+                var parentEntityTypeKey = extractDerivedFrom(entityType, result);
+                if (parentEntityTypeKey == null) {
+                    continue;
+                }
+                if (!isTypePresent(parentEntityTypeKey, reference)) {
+                    result.addResult("parent", parentEntityTypeKey, ValidationStatus.INVALID,
+                            Validated.NOT_FOUND);
+                }
+            }
+        }
+    }
+
+    /**
+     * validate all the ancestors of an entity type.
+     *
+     * @param entityTypesList the set of entity types that exist
+     * @param result the result of the ancestor search with any warnings or errors
+     */
+    private static <T extends DocToscaEntity<?>> void validEntityTypeAncestors(List<Map<String, T>> entityTypesList,
+            Set<String> reference, @NonNull final BeanValidationResult result) {
+        if (entityTypesList != null) {
+            for (var entityTypes : entityTypesList) {
+                for (var entityType : entityTypes.values()) {
+                    var parentEntityTypeKey = extractDerivedFrom(entityType, result);
+                    if (parentEntityTypeKey == null) {
+                        continue;
+                    }
+                    if (!isTypePresent(parentEntityTypeKey, reference)) {
+                        result.addResult("parent", parentEntityTypeKey, ValidationStatus.INVALID,
+                                Validated.NOT_FOUND);
+                    }
+                }
+            }
+        }
+    }
+
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaCapabilityAssignment.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaCapabilityAssignment.java
new file mode 100644 (file)
index 0000000..9caefe2
--- /dev/null
@@ -0,0 +1,106 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.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.ToString;
+import org.onap.policy.common.parameters.annotations.NotNull;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaCapabilityAssignment;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+@ToString(callSuper = true)
+public class DocToscaCapabilityAssignment extends DocToscaWithTypeAndStringProperties<ToscaCapabilityAssignment> {
+
+    private static final long serialVersionUID = 1L;
+
+    private Map<@NotNull String, @NotNull Object> attributes;
+    private List<@NotNull Object> occurrences;
+
+    /**
+     * Authorative constructor.
+     *
+     * @param authorativeConcept the authorative concept to copy from
+     */
+    public DocToscaCapabilityAssignment(final ToscaCapabilityAssignment authorativeConcept) {
+        fromAuthorative(authorativeConcept);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaCapabilityAssignment(final DocToscaCapabilityAssignment copyConcept) {
+        super(copyConcept);
+        this.attributes = copyConcept.attributes == null ? null : new LinkedHashMap<>(copyConcept.attributes);
+        this.occurrences = copyConcept.occurrences == null ? null : new ArrayList<>(copyConcept.occurrences);
+    }
+
+    @Override
+    public ToscaCapabilityAssignment toAuthorative() {
+        var toscaCapabilityAssignment = new ToscaCapabilityAssignment();
+        super.setToscaEntity(toscaCapabilityAssignment);
+        super.toAuthorative();
+
+        toscaCapabilityAssignment.setAttributes(PfUtils.mapMap(attributes, attribute -> attribute));
+        toscaCapabilityAssignment.setOccurrences(PfUtils.mapList(occurrences, occurrence -> occurrence));
+
+        return toscaCapabilityAssignment;
+    }
+
+    @Override
+    public void fromAuthorative(ToscaCapabilityAssignment toscaCapabilityAssignment) {
+        super.fromAuthorative(toscaCapabilityAssignment);
+
+        attributes = PfUtils.mapMap(toscaCapabilityAssignment.getAttributes(), attribute -> attribute);
+        occurrences = PfUtils.mapList(toscaCapabilityAssignment.getOccurrences(), occurrence -> occurrence);
+    }
+
+    @Override
+    public int compareTo(DocToscaEntity<ToscaCapabilityAssignment> otherConcept) {
+        if (this == otherConcept) {
+            return 0;
+        }
+
+        int result = super.compareTo(otherConcept);
+        if (result != 0) {
+            return result;
+        }
+
+        final var other = (DocToscaCapabilityAssignment) otherConcept;
+
+        result = PfUtils.compareMaps(attributes, other.attributes);
+        if (result != 0) {
+            return result;
+        }
+
+        return PfUtils.compareCollections(occurrences, other.occurrences);
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaCapabilityType.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaCapabilityType.java
new file mode 100644 (file)
index 0000000..38e790e
--- /dev/null
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import org.onap.policy.common.parameters.BeanValidationResult;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaCapabilityType;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class DocToscaCapabilityType extends DocToscaWithToscaProperties<ToscaCapabilityType> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Authorative constructor.
+     *
+     * @param authorativeConcept the authorative concept to copy from
+     */
+    public DocToscaCapabilityType(final ToscaCapabilityType authorativeConcept) {
+        fromAuthorative(authorativeConcept);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaCapabilityType(DocToscaCapabilityType copyConcept) {
+        super(copyConcept);
+    }
+
+    @Override
+    public ToscaCapabilityType toAuthorative() {
+        super.setToscaEntity(new ToscaCapabilityType());
+        return super.toAuthorative();
+    }
+
+    @Override
+    public BeanValidationResult validate(@NonNull String fieldName) {
+        return validateWithKey(fieldName);
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaConstraint.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaConstraint.java
new file mode 100644 (file)
index 0000000..f5b60a1
--- /dev/null
@@ -0,0 +1,107 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.onap.policy.models.base.PfAuthorative;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConstraint;
+
+@Data
+@NoArgsConstructor
+public class DocToscaConstraint implements PfAuthorative<ToscaConstraint>, Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @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;
+
+    public DocToscaConstraint(ToscaConstraint toscaConstraint) {
+        fromAuthorative(toscaConstraint);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaConstraint(final DocToscaConstraint copyConcept) {
+        this.validValues = copyConcept.validValues == null ? null : new ArrayList<>(copyConcept.validValues);
+        this.equal = copyConcept.equal;
+        this.greaterThan = copyConcept.greaterThan;
+        this.greaterOrEqual = copyConcept.greaterOrEqual;
+        this.lessThan = copyConcept.lessThan;
+        this.lessOrEqual = copyConcept.lessOrEqual;
+        this.rangeValues = copyConcept.rangeValues == null ? null : new ArrayList<>(copyConcept.rangeValues);
+    }
+
+    @Override
+    public ToscaConstraint toAuthorative() {
+        var toscaConstraint = new ToscaConstraint();
+        if (validValues != null) {
+            toscaConstraint.setValidValues(new ArrayList<>(validValues));
+        }
+        toscaConstraint.setEqual(equal);
+        toscaConstraint.setGreaterThan(greaterThan);
+        toscaConstraint.setGreaterOrEqual(greaterOrEqual);
+        toscaConstraint.setLessOrEqual(lessOrEqual);
+        if (rangeValues != null) {
+            toscaConstraint.setRangeValues(new ArrayList<>(rangeValues));
+        }
+        return toscaConstraint;
+    }
+
+    @Override
+    public void fromAuthorative(ToscaConstraint toscaConstraint) {
+        if (toscaConstraint.getValidValues() != null) {
+            validValues = new ArrayList<>(toscaConstraint.getValidValues());
+        }
+        equal = toscaConstraint.getEqual();
+        greaterThan = toscaConstraint.getGreaterThan();
+        greaterOrEqual = toscaConstraint.getGreaterOrEqual();
+        lessThan = toscaConstraint.getLessThan();
+        lessOrEqual = toscaConstraint.getLessOrEqual();
+        if (toscaConstraint.getRangeValues() != null) {
+            rangeValues = new ArrayList<>(toscaConstraint.getRangeValues());
+        }
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaDataType.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaDataType.java
new file mode 100644 (file)
index 0000000..73ffe17
--- /dev/null
@@ -0,0 +1,87 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.onap.policy.common.parameters.annotations.NotNull;
+import org.onap.policy.common.parameters.annotations.Valid;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class DocToscaDataType extends DocToscaWithToscaProperties<ToscaDataType> {
+
+    private static final long serialVersionUID = 1L;
+
+    private List<@NotNull @Valid DocToscaConstraint> constraints;
+
+    public DocToscaDataType(final ToscaDataType toscaDataType) {
+        fromAuthorative(toscaDataType);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaDataType(final DocToscaDataType copyConcept) {
+        super(copyConcept);
+        this.constraints = PfUtils.mapList(copyConcept.constraints, DocToscaConstraint::new);
+    }
+
+    @Override
+    public ToscaDataType toAuthorative() {
+        var toscaDataType = new ToscaDataType();
+        super.setToscaEntity(toscaDataType);
+        super.toAuthorative();
+        toscaDataType.setConstraints(PfUtils.mapList(constraints, DocToscaConstraint::toAuthorative));
+
+        return toscaDataType;
+    }
+
+    @Override
+    public void fromAuthorative(final ToscaDataType toscaDataType) {
+        super.fromAuthorative(toscaDataType);
+
+        constraints = PfUtils.mapList(toscaDataType.getConstraints(), DocToscaConstraint::new);
+    }
+
+    @Override
+    public int compareTo(DocToscaEntity<ToscaDataType> otherConcept) {
+        if (this == otherConcept) {
+            return 0;
+        }
+
+        int result = super.compareTo(otherConcept);
+        if (result != 0) {
+            return result;
+        }
+
+        final var other = (DocToscaDataType) otherConcept;
+
+        return PfUtils.compareCollections(constraints, other.constraints);
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaEntity.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaEntity.java
new file mode 100644 (file)
index 0000000..5d173af
--- /dev/null
@@ -0,0 +1,196 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import java.io.Serializable;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.ObjectUtils;
+import org.onap.policy.clamp.models.acm.document.base.DocConceptKey;
+import org.onap.policy.common.parameters.annotations.NotBlank;
+import org.onap.policy.common.parameters.annotations.NotNull;
+import org.onap.policy.models.base.PfAuthorative;
+import org.onap.policy.models.base.PfConceptKey;
+import org.onap.policy.models.base.PfKey;
+import org.onap.policy.models.base.PfNameVersion;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.base.Validated;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaEntity;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaEntityKey;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class DocToscaEntity<T extends ToscaEntity> extends Validated
+        implements PfNameVersion, PfAuthorative<T>, Serializable, Comparable<DocToscaEntity<T>> {
+
+    private static final long serialVersionUID = 1L;
+
+    @NotNull
+    private String name = PfKey.NULL_KEY_NAME;
+
+    @NotNull
+    private String version = PfKey.NULL_KEY_VERSION;
+
+    @SerializedName("derived_from")
+    private String derivedFrom;
+
+    private Map<@NotNull @NotBlank String, @NotNull @NotBlank Object> metadata = new LinkedHashMap<>();
+
+    @NotBlank
+    private String description;
+
+    private transient T toscaEntity;
+
+    /**
+     * Get a key for this entity.
+     *
+     * @return a ToscaEntityKey for this entry
+     */
+    public ToscaEntityKey getKey() {
+        return new ToscaEntityKey(name, version);
+    }
+
+    /**
+     * Get a key for this entity.
+     *
+     * @return a PfConceptKey for this entry
+     */
+    public PfConceptKey getConceptKey() {
+        return new PfConceptKey(name, version);
+    }
+
+    public DocConceptKey getDocConceptKey() {
+        return new DocConceptKey(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);
+    }
+
+    /**
+     * 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;
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaEntity(final DocToscaEntity<T> copyConcept) {
+        this.name = copyConcept.name;
+        this.version = copyConcept.version;
+        this.derivedFrom = copyConcept.derivedFrom;
+        this.metadata = (copyConcept.metadata != null ? new LinkedHashMap<>(copyConcept.metadata) : null);
+        this.description = copyConcept.description;
+    }
+
+    @Override
+    public T toAuthorative() {
+        toscaEntity.setName(getName());
+        toscaEntity.setVersion(getVersion());
+
+        if (derivedFrom != null) {
+            toscaEntity.setDerivedFrom(derivedFrom);
+        }
+
+        if (description != null) {
+            toscaEntity.setDescription(description);
+        }
+
+        toscaEntity.setMetadata(metadata);
+
+        return toscaEntity;
+    }
+
+    @Override
+    public void fromAuthorative(T toscaEntity) {
+        if (toscaEntity.getName() != null) {
+            name = toscaEntity.getName();
+        }
+        if (toscaEntity.getVersion() != null) {
+            version = toscaEntity.getVersion();
+        }
+        if (toscaEntity.getDerivedFrom() != null) {
+            derivedFrom = toscaEntity.getDerivedFrom();
+        }
+
+        if (toscaEntity.getDescription() != null) {
+            description = toscaEntity.getDescription();
+        }
+
+        metadata = toscaEntity.getMetadata();
+    }
+
+    @Override
+    public int compareTo(final DocToscaEntity<T> otherConcept) {
+        if (otherConcept == null) {
+            return -1;
+        }
+        if (this == otherConcept) {
+            return 0;
+        }
+        if (getClass() != otherConcept.getClass()) {
+            return getClass().getName().compareTo(otherConcept.getClass().getName());
+        }
+
+        int result = getKey().asIdentifier().compareTo(otherConcept.getKey().asIdentifier());
+        if (result != 0) {
+            return result;
+        }
+
+        result = ObjectUtils.compare(derivedFrom, otherConcept.derivedFrom);
+        if (result != 0) {
+            return result;
+        }
+
+        result = PfUtils.compareMaps(metadata, otherConcept.metadata);
+        if (result != 0) {
+            return result;
+        }
+
+        return ObjectUtils.compare(description, otherConcept.description);
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaNodeTemplate.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaNodeTemplate.java
new file mode 100644 (file)
index 0000000..acd42ba
--- /dev/null
@@ -0,0 +1,112 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import java.util.List;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+import org.onap.policy.clamp.models.acm.document.base.DocUtil;
+import org.onap.policy.common.parameters.annotations.Valid;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+@ToString(callSuper = true)
+public class DocToscaNodeTemplate extends DocToscaWithTypeAndStringProperties<ToscaNodeTemplate> {
+
+    private static final long serialVersionUID = 1L;
+
+    private List<Map<String, @Valid DocToscaRequirement>> requirements;
+
+    private Map<String, @Valid DocToscaCapabilityAssignment> capabilities;
+
+    /**
+     * Authorative constructor.
+     *
+     * @param authorativeConcept the authorative concept to copy from
+     */
+    public DocToscaNodeTemplate(final ToscaNodeTemplate authorativeConcept) {
+        this.fromAuthorative(authorativeConcept);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaNodeTemplate(final DocToscaNodeTemplate copyConcept) {
+        super(copyConcept);
+        this.requirements =
+                PfUtils.mapList(copyConcept.requirements, map -> DocUtil.docMapToMap(map, DocToscaRequirement::new));
+        this.capabilities = DocUtil.docMapToMap(copyConcept.capabilities, DocToscaCapabilityAssignment::new);
+    }
+
+    @Override
+    public ToscaNodeTemplate toAuthorative() {
+        var toscaNodeTemplate = new ToscaNodeTemplate();
+        super.setToscaEntity(toscaNodeTemplate);
+        super.toAuthorative();
+
+        toscaNodeTemplate.setRequirements(
+                PfUtils.mapList(requirements, map -> DocUtil.docMapToMap(map, DocToscaRequirement::toAuthorative)));
+
+        toscaNodeTemplate
+                .setCapabilities(DocUtil.docMapToMap(capabilities, DocToscaCapabilityAssignment::toAuthorative));
+
+        return toscaNodeTemplate;
+    }
+
+    @Override
+    public void fromAuthorative(ToscaNodeTemplate toscaNodeTemplate) {
+        super.fromAuthorative(toscaNodeTemplate);
+
+        requirements = PfUtils.mapList(toscaNodeTemplate.getRequirements(),
+                map -> DocUtil.mapToDocMap(map, DocToscaRequirement::new));
+
+        capabilities = DocUtil.mapToDocMap(toscaNodeTemplate.getCapabilities(), DocToscaCapabilityAssignment::new);
+    }
+
+    @Override
+    public int compareTo(DocToscaEntity<ToscaNodeTemplate> otherConcept) {
+        if (this == otherConcept) {
+            return 0;
+        }
+
+        int result = super.compareTo(otherConcept);
+        if (result != 0) {
+            return result;
+        }
+
+        final var other = (DocToscaNodeTemplate) otherConcept;
+
+        result = PfUtils.compareCollections(requirements, other.requirements);
+        if (result != 0) {
+            return result;
+        }
+
+        return PfUtils.compareMaps(capabilities, other.capabilities);
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaNodeType.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaNodeType.java
new file mode 100644 (file)
index 0000000..9f79b20
--- /dev/null
@@ -0,0 +1,90 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import java.util.List;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.onap.policy.clamp.models.acm.document.base.DocUtil;
+import org.onap.policy.common.parameters.annotations.Valid;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeType;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class DocToscaNodeType extends DocToscaWithToscaProperties<ToscaNodeType> {
+
+    private static final long serialVersionUID = 1L;
+
+    private List<Map<String, @Valid DocToscaRequirement>> requirements;
+
+    public DocToscaNodeType(ToscaNodeType toscaNodeType) {
+        fromAuthorative(toscaNodeType);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaNodeType(final DocToscaNodeType copyConcept) {
+        super(copyConcept);
+        this.requirements =
+                PfUtils.mapList(copyConcept.requirements, map -> DocUtil.docMapToMap(map, DocToscaRequirement::new));
+    }
+
+    @Override
+    public ToscaNodeType toAuthorative() {
+        var toscaNodeType = new ToscaNodeType();
+        super.setToscaEntity(toscaNodeType);
+        super.toAuthorative();
+        toscaNodeType.setRequirements(
+                PfUtils.mapList(requirements, map -> DocUtil.docMapToMap(map, DocToscaRequirement::toAuthorative)));
+
+        return toscaNodeType;
+    }
+
+    @Override
+    public void fromAuthorative(ToscaNodeType toscaNodeType) {
+        super.fromAuthorative(toscaNodeType);
+        requirements = PfUtils.mapList(toscaNodeType.getRequirements(),
+                map -> DocUtil.mapToDocMap(map, DocToscaRequirement::new));
+    }
+
+    @Override
+    public int compareTo(DocToscaEntity<ToscaNodeType> otherConcept) {
+        if (this == otherConcept) {
+            return 0;
+        }
+
+        int result = super.compareTo(otherConcept);
+        if (result != 0) {
+            return result;
+        }
+
+        final var other = (DocToscaNodeType) otherConcept;
+
+        return PfUtils.compareCollections(requirements, other.requirements);
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaParameter.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaParameter.java
new file mode 100644 (file)
index 0000000..ab7894a
--- /dev/null
@@ -0,0 +1,114 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.onap.policy.common.parameters.annotations.NotNull;
+import org.onap.policy.models.base.PfAuthorative;
+import org.onap.policy.models.base.PfKey;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaParameter;
+
+@Data
+@NoArgsConstructor
+public class DocToscaParameter implements PfAuthorative<ToscaParameter>, Serializable, Comparable<DocToscaParameter> {
+
+    private static final long serialVersionUID = 1L;
+
+    @NotNull
+    private String name;
+
+    @NotNull
+    private String type;
+
+    @NotNull
+    @SerializedName("type_version")
+    private String typeVersion;
+
+    private Object value;
+
+    /**
+     * Authorative constructor.
+     *
+     * @param authorativeConcept the authorative concept to copy from
+     */
+    public DocToscaParameter(final ToscaParameter authorativeConcept) {
+        this.fromAuthorative(authorativeConcept);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaParameter(final DocToscaParameter copyConcept) {
+        this.name = copyConcept.name;
+        this.type = copyConcept.type;
+        this.typeVersion = copyConcept.typeVersion;
+        this.value = copyConcept.value;
+    }
+
+    @Override
+    public ToscaParameter toAuthorative() {
+        var toscaParameter = new ToscaParameter();
+
+        toscaParameter.setName(name);
+        toscaParameter.setType(type);
+        toscaParameter.setTypeVersion(typeVersion);
+        toscaParameter.setValue(value);
+
+        return toscaParameter;
+    }
+
+    @Override
+    public void fromAuthorative(ToscaParameter toscaParameter) {
+        name = toscaParameter.getName();
+        type = toscaParameter.getType();
+
+        if (toscaParameter.getTypeVersion() != null) {
+            typeVersion = toscaParameter.getTypeVersion();
+        } else {
+            typeVersion = PfKey.NULL_KEY_VERSION;
+        }
+
+        value = toscaParameter.getValue();
+    }
+
+    @Override
+    public int compareTo(DocToscaParameter otherConcept) {
+        if (otherConcept == null) {
+            return -1;
+        }
+        if (this == otherConcept) {
+            return 0;
+        }
+
+        int result = name.compareTo(otherConcept.name);
+        if (result != 0) {
+            return result;
+        }
+
+        return PfUtils.compareObjects(value, otherConcept.value);
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaPolicy.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaPolicy.java
new file mode 100644 (file)
index 0000000..7b2291b
--- /dev/null
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import java.util.LinkedHashMap;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import lombok.ToString;
+import org.onap.policy.common.parameters.BeanValidationResult;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+@ToString(callSuper = true)
+public class DocToscaPolicy extends DocToscaWithTypeAndStringProperties<ToscaPolicy> {
+
+    private static final long serialVersionUID = 1L;
+
+    // Tags for metadata
+    private static final String METADATA_POLICY_ID_TAG = "policy-id";
+    private static final String METADATA_POLICY_VERSION_TAG = "policy-version";
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyObject object to copy
+     */
+    public DocToscaPolicy(@NonNull ToscaPolicy copyObject) {
+        this.fromAuthorative(copyObject);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaPolicy(final DocToscaPolicy copyConcept) {
+        super(copyConcept);
+    }
+
+    @Override
+    public ToscaPolicy toAuthorative() {
+        var toscaPolicy = new ToscaPolicy();
+        super.setToscaEntity(toscaPolicy);
+        super.toAuthorative();
+
+        return toscaPolicy;
+    }
+
+    @Override
+    public void fromAuthorative(ToscaPolicy toscaPolicy) {
+        super.fromAuthorative(toscaPolicy);
+
+        // Add the property metadata if it doesn't exist already
+        if (toscaPolicy.getMetadata() == null) {
+            setMetadata(new LinkedHashMap<>());
+        }
+
+        // Add the policy name and version fields to the metadata
+        getMetadata().put(METADATA_POLICY_ID_TAG, getKey().getName());
+        getMetadata().put(METADATA_POLICY_VERSION_TAG, getKey().getVersion());
+    }
+
+    @Override
+    public BeanValidationResult validate(String fieldName) {
+        var result = super.validate(fieldName);
+
+        validateKeyVersionNotNull(result, "key", getConceptKey());
+
+        return result;
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaPolicyType.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaPolicyType.java
new file mode 100644 (file)
index 0000000..a570144
--- /dev/null
@@ -0,0 +1,60 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class DocToscaPolicyType extends DocToscaWithToscaProperties<ToscaPolicyType> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Authorative constructor.
+     *
+     * @param authorativeConcept the authorative concept to copy from
+     */
+    public DocToscaPolicyType(final ToscaPolicyType authorativeConcept) {
+        fromAuthorative(authorativeConcept);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaPolicyType(final DocToscaPolicyType copyConcept) {
+        super(copyConcept);
+    }
+
+    @Override
+    public ToscaPolicyType toAuthorative() {
+        var toscaPolicyType = new ToscaPolicyType();
+        super.setToscaEntity(toscaPolicyType);
+        super.toAuthorative();
+        return toscaPolicyType;
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaProperty.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaProperty.java
new file mode 100644 (file)
index 0000000..1bcbd6b
--- /dev/null
@@ -0,0 +1,215 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import java.io.Serializable;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.ObjectUtils;
+import org.onap.policy.clamp.models.acm.document.base.DocConceptKey;
+import org.onap.policy.clamp.models.acm.document.base.DocUtil;
+import org.onap.policy.common.parameters.annotations.NotBlank;
+import org.onap.policy.common.parameters.annotations.NotNull;
+import org.onap.policy.common.parameters.annotations.Valid;
+import org.onap.policy.models.base.PfAuthorative;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaProperty;
+
+@Data
+@NoArgsConstructor
+public class DocToscaProperty implements PfAuthorative<ToscaProperty>, Serializable, Comparable<DocToscaProperty> {
+
+    private static final long serialVersionUID = 1L;
+
+    @NotNull
+    private String name;
+
+    @NotNull
+    private String type;
+
+    @SerializedName("type_version")
+    @NotNull
+    private String typeVersion;
+
+    @NotBlank
+    private String description;
+
+    @SerializedName("default")
+    @NotBlank
+    private Object defaultValue;
+
+    private boolean required = false;
+    private ToscaProperty.Status status;
+    private List<@NotNull @Valid DocToscaConstraint> constraints;
+
+    @SerializedName("key_schema")
+    @Valid
+    private DocToscaSchemaDefinition keySchema;
+
+    @SerializedName("entry_schema")
+    @Valid
+    private DocToscaSchemaDefinition entrySchema;
+
+    private Map<String, String> metadata;
+
+    public DocToscaProperty(ToscaProperty toscaProperty) {
+        fromAuthorative(toscaProperty);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaProperty(final DocToscaProperty copyConcept) {
+        this.name = copyConcept.name;
+        this.type = copyConcept.type;
+        this.typeVersion = copyConcept.typeVersion;
+        this.description = copyConcept.description;
+        this.defaultValue = copyConcept.defaultValue;
+        this.required = copyConcept.required;
+        this.status = copyConcept.status;
+        this.constraints = PfUtils.mapList(copyConcept.constraints, DocToscaConstraint::new);
+        if (copyConcept.keySchema != null) {
+            this.keySchema = new DocToscaSchemaDefinition(copyConcept.keySchema);
+        }
+        if (copyConcept.entrySchema != null) {
+            this.entrySchema = new DocToscaSchemaDefinition(copyConcept.entrySchema);
+        }
+        this.metadata = (copyConcept.metadata != null ? new LinkedHashMap<>(copyConcept.metadata) : null);
+    }
+
+    @Override
+    public ToscaProperty toAuthorative() {
+        var toscaProperty = new ToscaProperty();
+
+        toscaProperty.setName(name);
+        toscaProperty.setType(getTypeDocConceptKey().getId());
+        toscaProperty.setDescription(description);
+        toscaProperty.setRequired(required);
+        toscaProperty.setStatus(status);
+        toscaProperty.setDefaultValue(defaultValue);
+        toscaProperty.setConstraints(PfUtils.mapList(constraints, DocToscaConstraint::toAuthorative));
+
+        if (entrySchema != null) {
+            toscaProperty.setEntrySchema(entrySchema.toAuthorative());
+        }
+        if (keySchema != null) {
+            toscaProperty.setEntrySchema(keySchema.toAuthorative());
+        }
+
+        toscaProperty.setMetadata(PfUtils.mapMap(metadata, metadataItem -> metadataItem));
+
+        return toscaProperty;
+    }
+
+    @Override
+    public void fromAuthorative(ToscaProperty toscaProperty) {
+        name = toscaProperty.getName();
+
+        var key = DocUtil.createDocConceptKey(toscaProperty.getType(), toscaProperty.getTypeVersion());
+        type = key.getName();
+        typeVersion = key.getVersion();
+
+        description = toscaProperty.getDescription();
+        required = toscaProperty.isRequired();
+        status = toscaProperty.getStatus();
+        defaultValue = toscaProperty.getDefaultValue();
+        constraints = PfUtils.mapList(toscaProperty.getConstraints(), DocToscaConstraint::new);
+
+        if (toscaProperty.getEntrySchema() != null) {
+            entrySchema = new DocToscaSchemaDefinition(toscaProperty.getEntrySchema());
+        }
+        if (toscaProperty.getKeySchema() != null) {
+            keySchema = new DocToscaSchemaDefinition(toscaProperty.getKeySchema());
+        }
+
+        metadata = PfUtils.mapMap(toscaProperty.getMetadata(), metadataItem -> metadataItem);
+    }
+
+    public DocConceptKey getTypeDocConceptKey() {
+        return new DocConceptKey(type, typeVersion);
+    }
+
+    @Override
+    public int compareTo(DocToscaProperty otherConcept) {
+        if (otherConcept == null) {
+            return -1;
+        }
+        if (this == otherConcept) {
+            return 0;
+        }
+
+        int result = name.compareTo(otherConcept.name);
+        if (result != 0) {
+            return result;
+        }
+
+        return compareFields(otherConcept);
+    }
+
+    /**
+     * Compare the fields of this ToscaProperty object with the fields of the other ToscaProperty object.
+     *
+     * @param other the other ToscaProperty object
+     */
+    private int compareFields(final DocToscaProperty other) {
+        if (!type.equals(other.type)) {
+            return type.compareTo(other.type);
+        }
+
+        int result = ObjectUtils.compare(description, other.description);
+        if (result != 0) {
+            return result;
+        }
+
+        result = ObjectUtils.compare(required, other.required);
+        if (result != 0) {
+            return result;
+        }
+
+        result = PfUtils.compareObjects(defaultValue, other.defaultValue);
+        if (result != 0) {
+            return result;
+        }
+
+        result = ObjectUtils.compare(status, other.status);
+        if (result != 0) {
+            return result;
+        }
+
+        result = PfUtils.compareCollections(constraints, other.constraints);
+        if (result != 0) {
+            return result;
+        }
+
+        result = entrySchema.compareTo(other.entrySchema);
+        if (result != 0) {
+            return result;
+        }
+
+        return PfUtils.compareMaps(metadata, other.metadata);
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaRelationshipType.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaRelationshipType.java
new file mode 100644 (file)
index 0000000..5a650f1
--- /dev/null
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaRelationshipType;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class DocToscaRelationshipType extends DocToscaWithToscaProperties<ToscaRelationshipType> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * Authorative constructor.
+     *
+     * @param authorativeConcept the authorative concept to copy from
+     */
+    public DocToscaRelationshipType(final ToscaRelationshipType authorativeConcept) {
+        fromAuthorative(authorativeConcept);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaRelationshipType(final DocToscaRelationshipType copyConcept) {
+        super(copyConcept);
+    }
+
+    @Override
+    public ToscaRelationshipType toAuthorative() {
+        super.setToscaEntity(new ToscaRelationshipType());
+        return super.toAuthorative();
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaRequirement.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaRequirement.java
new file mode 100644 (file)
index 0000000..5bef710
--- /dev/null
@@ -0,0 +1,122 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import java.util.ArrayList;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaRequirement;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+@ToString(callSuper = true)
+public class DocToscaRequirement extends DocToscaWithTypeAndStringProperties<ToscaRequirement> {
+
+    private static final long serialVersionUID = 1L;
+
+    private String capability;
+    private String node;
+    private String relationship;
+    private List<Object> occurrences;
+
+    public DocToscaRequirement(ToscaRequirement toscaRequirement) {
+        fromAuthorative(toscaRequirement);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaRequirement(final DocToscaRequirement copyConcept) {
+        super(copyConcept);
+        this.capability = copyConcept.capability;
+        this.node = copyConcept.node;
+        this.relationship = copyConcept.relationship;
+        this.occurrences = new ArrayList<>(copyConcept.occurrences);
+    }
+
+    @Override
+    public ToscaRequirement toAuthorative() {
+        var toscaRequirement = new ToscaRequirement();
+        super.setToscaEntity(toscaRequirement);
+        super.toAuthorative();
+
+        toscaRequirement.setCapability(capability);
+        toscaRequirement.setNode(node);
+        toscaRequirement.setRelationship(relationship);
+
+        if (occurrences != null) {
+            toscaRequirement.setOccurrences(new ArrayList<>(occurrences));
+        }
+
+        return toscaRequirement;
+    }
+
+    @Override
+    public void fromAuthorative(ToscaRequirement toscaRequirement) {
+        super.fromAuthorative(toscaRequirement);
+
+        capability = toscaRequirement.getCapability();
+        node = toscaRequirement.getNode();
+        relationship = toscaRequirement.getRelationship();
+
+        if (toscaRequirement.getOccurrences() != null) {
+            occurrences = new ArrayList<>(toscaRequirement.getOccurrences());
+        }
+    }
+
+    @Override
+    public int compareTo(DocToscaEntity<ToscaRequirement> otherConcept) {
+        if (this == otherConcept) {
+            return 0;
+        }
+
+        int result = super.compareTo(otherConcept);
+        if (result != 0) {
+            return result;
+        }
+
+        final var other = (DocToscaRequirement) otherConcept;
+
+        result = capability.compareTo(other.capability);
+        if (result != 0) {
+            return result;
+        }
+
+        result = node.compareTo(other.node);
+        if (result != 0) {
+            return result;
+        }
+
+        result = relationship.compareTo(other.relationship);
+        if (result != 0) {
+            return result;
+        }
+
+        return PfUtils.compareCollections(occurrences, other.occurrences);
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaSchemaDefinition.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaSchemaDefinition.java
new file mode 100644 (file)
index 0000000..89b3c42
--- /dev/null
@@ -0,0 +1,119 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import java.io.Serializable;
+import java.util.List;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.ObjectUtils;
+import org.onap.policy.clamp.models.acm.document.base.DocConceptKey;
+import org.onap.policy.clamp.models.acm.document.base.DocUtil;
+import org.onap.policy.models.base.PfAuthorative;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaSchemaDefinition;
+
+@Data
+@NoArgsConstructor
+public class DocToscaSchemaDefinition
+        implements PfAuthorative<ToscaSchemaDefinition>, Serializable, Comparable<DocToscaSchemaDefinition> {
+
+    private static final long serialVersionUID = 1L;
+
+    private String name;
+    private String type;
+
+    @SerializedName("type_version")
+    private String typeVersion;
+
+    private String description;
+    private List<DocToscaConstraint> constraints;
+
+    public DocToscaSchemaDefinition(ToscaSchemaDefinition toscaEntrySchema) {
+        fromAuthorative(toscaEntrySchema);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaSchemaDefinition(final DocToscaSchemaDefinition copyConcept) {
+        this.name = copyConcept.name;
+        this.type = copyConcept.type;
+        this.typeVersion = copyConcept.typeVersion;
+        this.description = copyConcept.description;
+        this.constraints = PfUtils.mapList(copyConcept.constraints, DocToscaConstraint::new);
+    }
+
+    @Override
+    public ToscaSchemaDefinition toAuthorative() {
+        var toscaEntrySchema = new ToscaSchemaDefinition();
+
+        toscaEntrySchema.setName(name);
+        toscaEntrySchema.setType(getTypeDocConceptKey().getId());
+        toscaEntrySchema.setDescription(description);
+
+        if (constraints != null) {
+            toscaEntrySchema.setConstraints(PfUtils.mapList(constraints, DocToscaConstraint::toAuthorative));
+        }
+
+        return toscaEntrySchema;
+    }
+
+    @Override
+    public void fromAuthorative(ToscaSchemaDefinition toscaEntrySchema) {
+        name = toscaEntrySchema.getName();
+
+        var key = DocUtil.createDocConceptKey(toscaEntrySchema.getType(), toscaEntrySchema.getTypeVersion());
+        type = key.getName();
+        typeVersion = key.getVersion();
+
+        description = toscaEntrySchema.getDescription();
+
+        if (toscaEntrySchema.getConstraints() != null) {
+            constraints = PfUtils.mapList(toscaEntrySchema.getConstraints(), DocToscaConstraint::new);
+
+        }
+    }
+
+    public DocConceptKey getTypeDocConceptKey() {
+        return new DocConceptKey(type, typeVersion);
+    }
+
+    @Override
+    public int compareTo(DocToscaSchemaDefinition other) {
+        if (other == null) {
+            return -1;
+        }
+        if (this == other) {
+            return 0;
+        }
+
+        int result = ObjectUtils.compare(description, other.description);
+        if (result != 0) {
+            return result;
+        }
+
+        return PfUtils.compareCollections(constraints, other.constraints);
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaServiceTemplate.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaServiceTemplate.java
new file mode 100644 (file)
index 0000000..bd47452
--- /dev/null
@@ -0,0 +1,215 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.apache.commons.lang3.ObjectUtils;
+import org.onap.policy.clamp.models.acm.document.base.DocUtil;
+import org.onap.policy.common.parameters.annotations.NotBlank;
+import org.onap.policy.common.parameters.annotations.NotNull;
+import org.onap.policy.common.parameters.annotations.Valid;
+import org.onap.policy.models.base.PfKey;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class DocToscaServiceTemplate extends DocToscaEntity<ToscaServiceTemplate> {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final String DEFAULT_TOSCA_DEFINTIONS_VERISON = "tosca_simple_yaml_1_1_0";
+    public static final String DEFAULT_NAME = "tosca";
+    public static final String DEFAULT_VERSION = "1.0.0";
+
+    @SerializedName("tosca_definitions_version")
+    @NotNull
+    @NotBlank
+    private String toscaDefinitionsVersion;
+
+    @SerializedName("data_types")
+    private Map<String, @Valid DocToscaDataType> dataTypes;
+
+    @SerializedName("capability_types")
+    private Map<String, @Valid DocToscaCapabilityType> capabilityTypes;
+
+    @SerializedName("node_types")
+    private Map<String, @Valid DocToscaNodeType> nodeTypes;
+
+    @SerializedName("relationship_types")
+    private Map<String, @Valid DocToscaRelationshipType> relationshipTypes;
+
+    @SerializedName("policy_types")
+    private Map<String, @Valid DocToscaPolicyType> policyTypes;
+
+    @SerializedName("topology_template")
+    @Valid
+    private DocToscaTopologyTemplate toscaTopologyTemplate;
+
+    public DocToscaServiceTemplate(ToscaServiceTemplate authorativeConcept) {
+        this.fromAuthorative(authorativeConcept);
+    }
+
+    /**
+     * The Default Constructor creates a {@link DocToscaServiceTemplate} object with a null key.
+     */
+    public DocToscaServiceTemplate() {
+        super();
+        setName(DEFAULT_NAME);
+        setVersion(DEFAULT_VERSION);
+        setToscaDefinitionsVersion(DEFAULT_TOSCA_DEFINTIONS_VERISON);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaServiceTemplate(final DocToscaServiceTemplate copyConcept) {
+        super(copyConcept);
+        this.toscaDefinitionsVersion = copyConcept.toscaDefinitionsVersion;
+        this.dataTypes = DocUtil.docMapToMap(copyConcept.dataTypes, DocToscaDataType::new, new LinkedHashMap<>());
+        this.capabilityTypes =
+                DocUtil.docMapToMap(copyConcept.capabilityTypes, DocToscaCapabilityType::new, new LinkedHashMap<>());
+        this.nodeTypes = DocUtil.docMapToMap(copyConcept.nodeTypes, DocToscaNodeType::new, new LinkedHashMap<>());
+        this.relationshipTypes = DocUtil.docMapToMap(copyConcept.relationshipTypes, DocToscaRelationshipType::new,
+                new LinkedHashMap<>());
+        this.policyTypes = DocUtil.docMapToMap(copyConcept.policyTypes, DocToscaPolicyType::new, new LinkedHashMap<>());
+        if (copyConcept.toscaTopologyTemplate != null) {
+            this.toscaTopologyTemplate = new DocToscaTopologyTemplate(copyConcept.toscaTopologyTemplate);
+        }
+    }
+
+    @Override
+    public ToscaServiceTemplate toAuthorative() {
+        final var toscaServiceTemplate = new ToscaServiceTemplate();
+        super.setToscaEntity(toscaServiceTemplate);
+        super.toAuthorative();
+
+        toscaServiceTemplate.setToscaDefinitionsVersion(toscaDefinitionsVersion);
+        toscaServiceTemplate.setDataTypes(DocUtil.docMapToMap(dataTypes, DocToscaDataType::toAuthorative));
+        toscaServiceTemplate
+                .setCapabilityTypes(DocUtil.docMapToMap(capabilityTypes, DocToscaCapabilityType::toAuthorative));
+        toscaServiceTemplate
+                .setRelationshipTypes(DocUtil.docMapToMap(relationshipTypes, DocToscaRelationshipType::toAuthorative));
+        toscaServiceTemplate.setNodeTypes(DocUtil.docMapToMap(nodeTypes, DocToscaNodeType::toAuthorative));
+        toscaServiceTemplate.setPolicyTypes(DocUtil.docMapToMap(policyTypes, DocToscaPolicyType::toAuthorative));
+        toscaServiceTemplate.setToscaTopologyTemplate(toscaTopologyTemplate.toAuthorative());
+
+        return toscaServiceTemplate;
+    }
+
+    @Override
+    public void fromAuthorative(ToscaServiceTemplate toscaServiceTemplate) {
+        super.fromAuthorative(toscaServiceTemplate);
+        if (getVersion() == null || PfKey.NULL_KEY_VERSION.equals(getVersion())) {
+            setVersion(DEFAULT_VERSION);
+        }
+        if (getName() == null || PfKey.NULL_KEY_NAME.equals(getName())) {
+            setName(DEFAULT_NAME);
+        }
+
+        toscaDefinitionsVersion = toscaServiceTemplate.getToscaDefinitionsVersion();
+
+        dataTypes = DocUtil.mapToDocMap(toscaServiceTemplate.getDataTypes(), DocToscaDataType::new);
+
+        capabilityTypes = DocUtil.mapToDocMap(toscaServiceTemplate.getCapabilityTypes(), DocToscaCapabilityType::new);
+
+        relationshipTypes =
+                DocUtil.mapToDocMap(toscaServiceTemplate.getRelationshipTypes(), DocToscaRelationshipType::new);
+
+        nodeTypes = DocUtil.mapToDocMap(toscaServiceTemplate.getNodeTypes(), DocToscaNodeType::new);
+
+        if (toscaServiceTemplate.getPolicyTypes() != null) {
+            policyTypes = DocUtil.mapToDocMap(toscaServiceTemplate.getPolicyTypes(), DocToscaPolicyType::new);
+        }
+
+        if (toscaServiceTemplate.getToscaTopologyTemplate() != null) {
+            toscaTopologyTemplate = new DocToscaTopologyTemplate(toscaServiceTemplate.getToscaTopologyTemplate());
+        }
+    }
+
+    @Override
+    public int compareTo(DocToscaEntity<ToscaServiceTemplate> otherConcept) {
+        int result = compareToWithoutEntities(otherConcept);
+        if (result != 0) {
+            return result;
+        }
+
+        final DocToscaServiceTemplate other = (DocToscaServiceTemplate) otherConcept;
+
+        result = PfUtils.compareMaps(dataTypes, other.dataTypes);
+        if (result != 0) {
+            return result;
+        }
+
+        result = PfUtils.compareMaps(capabilityTypes, other.capabilityTypes);
+        if (result != 0) {
+            return result;
+        }
+
+        result = PfUtils.compareMaps(relationshipTypes, other.relationshipTypes);
+        if (result != 0) {
+            return result;
+        }
+
+        result = PfUtils.compareMaps(nodeTypes, other.nodeTypes);
+        if (result != 0) {
+            return result;
+        }
+
+        result = PfUtils.compareMaps(policyTypes, other.policyTypes);
+        if (result != 0) {
+            return result;
+        }
+
+        return ObjectUtils.compare(toscaTopologyTemplate, other.toscaTopologyTemplate);
+    }
+
+    /**
+     * Compare this service template to another service template, ignoring contained entitites.
+     *
+     * @param otherConcept the other topology template
+     * @return the result of the comparison
+     */
+    public int compareToWithoutEntities(final DocToscaEntity<ToscaServiceTemplate> otherConcept) {
+        if (otherConcept == null) {
+            return -1;
+        }
+        if (this == otherConcept) {
+            return 0;
+        }
+        if (getClass() != otherConcept.getClass()) {
+            return getClass().getName().compareTo(otherConcept.getClass().getName());
+        }
+
+        final var other = (DocToscaServiceTemplate) otherConcept;
+        if (!super.equals(other)) {
+            return super.compareTo(other);
+        }
+
+        return ObjectUtils.compare(toscaDefinitionsVersion, other.toscaDefinitionsVersion);
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaTopologyTemplate.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaTopologyTemplate.java
new file mode 100644 (file)
index 0000000..79a68e2
--- /dev/null
@@ -0,0 +1,143 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import java.io.Serializable;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.ObjectUtils;
+import org.onap.policy.clamp.models.acm.document.base.DocUtil;
+import org.onap.policy.common.parameters.annotations.Valid;
+import org.onap.policy.models.base.PfAuthorative;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.base.Validated;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaTopologyTemplate;
+
+@Data
+@NoArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class DocToscaTopologyTemplate extends Validated
+        implements PfAuthorative<ToscaTopologyTemplate>, Serializable, Comparable<DocToscaTopologyTemplate> {
+
+    private static final long serialVersionUID = 1L;
+
+    private String description;
+
+    private Map<String, @Valid DocToscaParameter> inputs;
+
+    @SerializedName("node_templates")
+    private Map<String, @Valid DocToscaNodeTemplate> nodeTemplates;
+
+    private Map<String, @Valid DocToscaPolicy> policies;
+
+    /**
+     * Authorative constructor.
+     *
+     * @param authorativeConcept the authorative concept to copy from
+     */
+    public DocToscaTopologyTemplate(final ToscaTopologyTemplate authorativeConcept) {
+        this.fromAuthorative(authorativeConcept);
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaTopologyTemplate(final DocToscaTopologyTemplate copyConcept) {
+        this.description = copyConcept.description;
+        this.inputs = PfUtils.mapMap(copyConcept.inputs, DocToscaParameter::new);
+        this.nodeTemplates =
+                DocUtil.docMapToMap(copyConcept.nodeTemplates, DocToscaNodeTemplate::new, new LinkedHashMap<>());
+        this.policies = DocUtil.docMapToMap(copyConcept.policies, DocToscaPolicy::new, new LinkedHashMap<>());
+    }
+
+    @Override
+    public ToscaTopologyTemplate toAuthorative() {
+        final var toscaTopologyTemplate = new ToscaTopologyTemplate();
+
+        toscaTopologyTemplate.setDescription(description);
+        toscaTopologyTemplate.setInputs(PfUtils.mapMap(inputs, DocToscaParameter::toAuthorative));
+        toscaTopologyTemplate.setNodeTemplates(DocUtil.docMapToMap(nodeTemplates, DocToscaNodeTemplate::toAuthorative));
+
+        toscaTopologyTemplate.setPolicies(DocUtil.docMapToList(policies, DocToscaPolicy::toAuthorative));
+
+        return toscaTopologyTemplate;
+    }
+
+    @Override
+    public void fromAuthorative(ToscaTopologyTemplate toscaTopologyTemplate) {
+        description = toscaTopologyTemplate.getDescription();
+
+        if (toscaTopologyTemplate.getInputs() != null) {
+            inputs = PfUtils.mapMap(toscaTopologyTemplate.getInputs(), DocToscaParameter::new);
+            for (var entry : inputs.entrySet()) {
+                if (entry.getValue().getName() == null) {
+                    entry.getValue().setName(entry.getKey());
+                }
+            }
+        }
+
+        nodeTemplates = DocUtil.mapToDocMap(toscaTopologyTemplate.getNodeTemplates(), DocToscaNodeTemplate::new);
+
+        policies = DocUtil.listToDocMap(toscaTopologyTemplate.getPolicies(), DocToscaPolicy::new);
+    }
+
+    @Override
+    public int compareTo(DocToscaTopologyTemplate otherConcept) {
+        int result = compareToWithoutEntities(otherConcept);
+        if (result != 0) {
+            return result;
+        }
+
+        result = PfUtils.compareMaps(inputs, otherConcept.inputs);
+        if (result != 0) {
+            return result;
+        }
+
+        result = PfUtils.compareMaps(nodeTemplates, otherConcept.nodeTemplates);
+        if (result != 0) {
+            return result;
+        }
+        return PfUtils.compareMaps(policies, otherConcept.policies);
+    }
+
+    /**
+     * Compare this topology template to another topology template, ignoring contained entities.
+     *
+     * @param otherConcept the other topology template
+     * @return the result of the comparison
+     */
+    public int compareToWithoutEntities(final DocToscaTopologyTemplate otherConcept) {
+        if (otherConcept == null) {
+            return -1;
+        }
+        if (this == otherConcept) {
+            return 0;
+        }
+
+        return ObjectUtils.compare(description, otherConcept.description);
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaWithToscaProperties.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaWithToscaProperties.java
new file mode 100644 (file)
index 0000000..3b53e1b
--- /dev/null
@@ -0,0 +1,122 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import org.apache.commons.collections4.CollectionUtils;
+import org.onap.policy.clamp.models.acm.document.base.DocConceptKey;
+import org.onap.policy.common.parameters.BeanValidationResult;
+import org.onap.policy.common.parameters.annotations.NotBlank;
+import org.onap.policy.common.parameters.annotations.NotNull;
+import org.onap.policy.common.parameters.annotations.Valid;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaWithToscaProperties;
+import org.onap.policy.models.tosca.utils.ToscaUtils;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+public class DocToscaWithToscaProperties<T extends ToscaWithToscaProperties> extends DocToscaEntity<T> {
+
+    private static final long serialVersionUID = 1L;
+
+    private Map<@NotNull @NotBlank String, @NotNull @Valid DocToscaProperty> properties;
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaWithToscaProperties(DocToscaWithToscaProperties<T> copyConcept) {
+        super(copyConcept);
+        this.properties = PfUtils.mapMap(copyConcept.properties, DocToscaProperty::new);
+    }
+
+    @Override
+    public T toAuthorative() {
+        var tosca = super.toAuthorative();
+        tosca.setProperties(PfUtils.mapMap(properties, DocToscaProperty::toAuthorative));
+        return tosca;
+    }
+
+    /**
+     * Validates the fields of the object, including its key.
+     *
+     * @param fieldName name of the field containing this
+     * @return the result, or {@code null}
+     */
+    protected BeanValidationResult validateWithKey(@NonNull String fieldName) {
+        var result = super.validate(fieldName);
+
+        validateKeyVersionNotNull(result, "key", getConceptKey());
+
+        return result;
+    }
+
+    @Override
+    public void fromAuthorative(T authorativeConcept) {
+        super.fromAuthorative(authorativeConcept);
+
+        // Set properties
+        if (authorativeConcept.getProperties() != null) {
+            properties = new LinkedHashMap<>();
+            for (var toscaPropertyEntry : authorativeConcept.getProperties().entrySet()) {
+                var jpaProperty = new DocToscaProperty(toscaPropertyEntry.getValue());
+                jpaProperty.setName(toscaPropertyEntry.getKey());
+                properties.put(toscaPropertyEntry.getKey(), jpaProperty);
+            }
+        }
+    }
+
+    /**
+     * Get the referenced data types.
+     *
+     * @return the referenced data types
+     */
+    public Collection<DocConceptKey> getReferencedDataTypes() {
+        if (properties == null) {
+            return CollectionUtils.emptyCollection();
+        }
+
+        Set<DocConceptKey> referencedDataTypes = new LinkedHashSet<>();
+
+        for (var property : properties.values()) {
+            referencedDataTypes.add(property.getTypeDocConceptKey());
+
+            if (property.getEntrySchema() != null) {
+                referencedDataTypes.add(property.getEntrySchema().getTypeDocConceptKey());
+            }
+        }
+
+        var set = ToscaUtils.getPredefinedDataTypes().stream().map(DocConceptKey::new).collect(Collectors.toSet());
+        referencedDataTypes.removeAll(set);
+        return referencedDataTypes;
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaWithTypeAndStringProperties.java b/models/src/main/java/org/onap/policy/clamp/models/acm/document/concepts/DocToscaWithTypeAndStringProperties.java
new file mode 100644 (file)
index 0000000..377cecb
--- /dev/null
@@ -0,0 +1,100 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.clamp.models.acm.document.concepts;
+
+import com.google.gson.annotations.SerializedName;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import javax.ws.rs.core.Response;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.ToString;
+import org.onap.policy.clamp.models.acm.document.base.DocConceptKey;
+import org.onap.policy.clamp.models.acm.document.base.DocUtil;
+import org.onap.policy.models.base.PfKey;
+import org.onap.policy.models.base.PfModelRuntimeException;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaWithTypeAndObjectProperties;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+@NoArgsConstructor
+@ToString
+public class DocToscaWithTypeAndStringProperties<T extends ToscaWithTypeAndObjectProperties> extends DocToscaEntity<T> {
+
+    private static final long serialVersionUID = 1L;
+
+    private String type;
+
+    @SerializedName("type_version")
+    private String typeVersion;
+
+    private Map<String, Object> properties;
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public DocToscaWithTypeAndStringProperties(final DocToscaWithTypeAndStringProperties<T> copyConcept) {
+        super(copyConcept);
+        this.type = copyConcept.type;
+        this.typeVersion = copyConcept.typeVersion;
+        this.properties = (copyConcept.properties != null ? new LinkedHashMap<>(copyConcept.properties) : null);
+    }
+
+    @Override
+    public T toAuthorative() {
+        var tosca = super.toAuthorative();
+
+        tosca.setType(getTypeDocConceptKey().getId());
+        tosca.setTypeVersion("");
+
+        tosca.setProperties(PfUtils.mapMap(properties, x -> x));
+
+        return tosca;
+    }
+
+    @Override
+    public void fromAuthorative(T authorativeConcept) {
+        super.fromAuthorative(authorativeConcept);
+        if (authorativeConcept.getType() == null) {
+            throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
+                    "Type not specified, the type of this TOSCA entity must be specified in the type field");
+        }
+        var key = DocUtil.createDocConceptKey(authorativeConcept.getType(), authorativeConcept.getTypeVersion());
+        type = key.getName();
+        typeVersion = key.getVersion();
+
+        if (PfKey.NULL_KEY_VERSION.equals(typeVersion)) {
+            throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
+                    "Version not specified, the version of this TOSCA entity must be specified"
+                            + " in the type_version field");
+        }
+
+        properties = PfUtils.mapMap(authorativeConcept.getProperties(), x -> x);
+    }
+
+    public DocConceptKey getTypeDocConceptKey() {
+        return new DocConceptKey(type, typeVersion);
+    }
+}
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/StringToServiceTemplateConverter.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/StringToServiceTemplateConverter.java
new file mode 100644 (file)
index 0000000..79e6912
--- /dev/null
@@ -0,0 +1,57 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  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.clamp.models.acm.persistence.concepts;
+
+import javax.persistence.AttributeConverter;
+import javax.persistence.Converter;
+import javax.ws.rs.core.Response;
+import org.onap.policy.clamp.models.acm.document.concepts.DocToscaServiceTemplate;
+import org.onap.policy.common.utils.coder.Coder;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.models.base.PfModelRuntimeException;
+
+@Converter(autoApply = true)
+public class StringToServiceTemplateConverter implements AttributeConverter<DocToscaServiceTemplate, String> {
+
+    private static final Coder coder = new StandardCoder();
+
+    @Override
+    public String convertToDatabaseColumn(DocToscaServiceTemplate serviceTemplate) {
+        try {
+            return serviceTemplate == null ? null : coder.encode(serviceTemplate);
+        } catch (CoderException e) {
+            throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public DocToscaServiceTemplate convertToEntityAttribute(String dbData) {
+        if (dbData == null) {
+            return new DocToscaServiceTemplate();
+        }
+        try {
+            return coder.decode(dbData, DocToscaServiceTemplate.class);
+        } catch (CoderException e) {
+            throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, e.getMessage(), e);
+        }
+    }
+}