2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2022-2026 OpenInfra Foundation Europe. All rights reserved.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.clamp.models.acm.document.base;
23 import java.util.Collection;
24 import java.util.List;
27 import lombok.AccessLevel;
28 import lombok.NoArgsConstructor;
29 import lombok.NonNull;
30 import org.onap.policy.clamp.models.acm.document.concepts.DocToscaEntity;
31 import org.onap.policy.clamp.models.acm.document.concepts.DocToscaServiceTemplate;
32 import org.onap.policy.clamp.models.acm.document.concepts.DocToscaTopologyTemplate;
33 import org.onap.policy.common.parameters.BeanValidationResult;
34 import org.onap.policy.common.parameters.ValidationStatus;
35 import org.onap.policy.models.base.PfUtils;
37 @NoArgsConstructor(access = AccessLevel.PRIVATE)
38 public final class ToscaServiceTemplateValidation {
40 private static final String ROOT_KEY_NAME_SUFFIX = ".Root";
41 private static final String TOPOLOGY_TEMPLATE = "TopologyTemplate";
42 private static final String NOT_FOUND = "not found";
45 * validate a serviceTemplate.
47 * @param result the result
48 * @param serviceTemplate the serviceTemplate to validate
50 public static void validate(final @NonNull BeanValidationResult result, DocToscaServiceTemplate serviceTemplate,
51 String toscaCompositionName) {
53 var references = DocUtil.getToscaReferences(serviceTemplate);
55 validEntityTypeAncestors(serviceTemplate.getDataTypes(), references.get(DocUtil.REF_DATA_TYPES), result);
56 validEntityTypeAncestors(serviceTemplate.getCapabilityTypes(), references.get(DocUtil.REF_CAPABILITY_TYPES),
58 validEntityTypeAncestors(serviceTemplate.getNodeTypes(), references.get(DocUtil.REF_NODE_TYPES), result);
59 validEntityTypeAncestors(serviceTemplate.getRelationshipTypes(), references.get(DocUtil.REF_RELATIONSHIP_TYPES),
61 validEntityTypeAncestors(serviceTemplate.getPolicyTypes(), references.get(DocUtil.REF_POLICY_TYPES), result);
63 if (serviceTemplate.getNodeTypes() != null) {
64 for (var nodeType : serviceTemplate.getNodeTypes().values()) {
65 validEntityTypeAncestors(nodeType.getRequirements(), references.get(DocUtil.REF_REQUIREMENTS), result);
69 validateToscaTopologyTemplate(result, serviceTemplate.getToscaTopologyTemplate(), toscaCompositionName);
71 if (serviceTemplate.getToscaTopologyTemplate() != null) {
72 validEntityTypeAncestors(serviceTemplate.getToscaTopologyTemplate().getNodeTemplates(),
73 references.get(DocUtil.REF_NODE_TEMPLATES), result);
74 validEntityTypeAncestors(serviceTemplate.getToscaTopologyTemplate().getPolicies(),
75 references.get(DocUtil.REF_POLICIES), result);
77 if (serviceTemplate.getToscaTopologyTemplate().getNodeTemplates() != null) {
78 for (var nodeTemplate : serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().values()) {
79 validEntityTypeAncestors(nodeTemplate.getCapabilities(), references.get(DocUtil.REF_CAPABILITIES),
81 validEntityTypeAncestors(nodeTemplate.getRequirements(), references.get(DocUtil.REF_REQUIREMENTS),
87 validateReferencedDataTypes(result, serviceTemplate, references);
89 validatePolicyTypesInPolicies(result, serviceTemplate, references);
94 * Validate ToscaTopologyTemplate.
96 * @param result the BeanValidationResult
97 * @param topologyTemplate the ToscaServiceTemplate
98 * @param toscaCompositionName the name of the ToscaComposition
100 public static void validateToscaTopologyTemplate(final @NonNull BeanValidationResult result,
101 DocToscaTopologyTemplate topologyTemplate, String toscaCompositionName) {
102 String acNodeTypeNotPresent =
103 "NodeTemplate with type " + toscaCompositionName + " must exist!";
105 if (topologyTemplate != null && topologyTemplate.getNodeTemplates() != null) {
106 var nodeTemplates = topologyTemplate.getNodeTemplates();
107 var acNumber = nodeTemplates.values().stream().filter(
108 nodeTemplate -> toscaCompositionName.equals(nodeTemplate.getType()))
111 result.addResult(TOPOLOGY_TEMPLATE, nodeTemplates, ValidationStatus.INVALID, acNodeTypeNotPresent);
114 result.addResult(TOPOLOGY_TEMPLATE, nodeTemplates, ValidationStatus.INVALID, "NodeTemplate with type "
115 + toscaCompositionName + " not allowed to be more than one!");
118 result.addResult(TOPOLOGY_TEMPLATE, topologyTemplate, ValidationStatus.INVALID, acNodeTypeNotPresent);
123 * Validate that all data types referenced in policy types exist.
125 * @param result where the results are added
127 private static void validateReferencedDataTypes(final BeanValidationResult result,
128 DocToscaServiceTemplate serviceTemplate, Map<String, Set<String>> references) {
129 if (serviceTemplate.getDataTypes() != null) {
130 for (var dataType : serviceTemplate.getDataTypes().values()) {
131 validateReferencedDataTypesExists(result, dataType.getReferencedDataTypes(), references);
135 if (serviceTemplate.getPolicyTypes() != null) {
136 for (var policyType : serviceTemplate.getPolicyTypes().values()) {
137 validateReferencedDataTypesExists(result, policyType.getReferencedDataTypes(), references);
140 if (serviceTemplate.getNodeTypes() != null) {
141 for (var nodeType : serviceTemplate.getNodeTypes().values()) {
142 validateReferencedDataTypesExists(result, nodeType.getReferencedDataTypes(), references);
148 * Validate that the referenced data types exist for a collection of data type keys.
150 * @param dataTypeKeyCollection the data type key collection
151 * @param result where the results are added
153 private static void validateReferencedDataTypesExists(final BeanValidationResult result,
154 final Collection<DocConceptKey> dataTypeKeyCollection, Map<String, Set<String>> references) {
155 for (DocConceptKey dataTypeKey : dataTypeKeyCollection) {
156 if (!isTypePresent(dataTypeKey, references.get(DocUtil.REF_DATA_TYPES))) {
158 "data type", PfUtils.getId(dataTypeKey), ValidationStatus.INVALID, NOT_FOUND);
164 * Validate that all policy types referenced in policies exist.
166 * @param result where the results are added
168 private static void validatePolicyTypesInPolicies(final BeanValidationResult result,
169 DocToscaServiceTemplate serviceTemplate, Map<String, Set<String>> references) {
170 if (serviceTemplate.getToscaTopologyTemplate() == null) {
174 if (serviceTemplate.getToscaTopologyTemplate().getPolicies() != null) {
175 for (var policy : serviceTemplate.getToscaTopologyTemplate().getPolicies().values()) {
176 var key = policy.getTypeDocConceptKey();
177 if (!isTypePresent(key, references.get(DocUtil.REF_POLICY_TYPES))) {
178 result.addResult("policy type", key, ValidationStatus.INVALID, NOT_FOUND);
182 if (serviceTemplate.getToscaTopologyTemplate().getNodeTemplates() != null) {
183 for (var nodeTemplate : serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().values()) {
184 var key = nodeTemplate.getTypeDocConceptKey();
185 if (!isTypePresent(key, references.get(DocUtil.REF_NODE_TYPES))) {
186 result.addResult("node Template", key, ValidationStatus.INVALID, NOT_FOUND);
192 private static boolean isTypePresent(String key, Set<String> reference) {
193 if (reference.isEmpty()) {
196 return reference.contains(key);
199 private static boolean isTypePresent(DocConceptKey key, Set<String> reference) {
200 if (reference.isEmpty()) {
203 return reference.contains(PfUtils.getId(key));
206 private static String extractDerivedFrom(DocToscaEntity<?> entityType, final BeanValidationResult result) {
207 if (entityType.getDerivedFrom() == null) {
210 var parentEntityTypeKey = entityType.getDerivedFrom();
212 if (parentEntityTypeKey.endsWith(ROOT_KEY_NAME_SUFFIX)) {
215 if (entityType.getName().equals(parentEntityTypeKey)) {
216 result.addResult("entity type", PfUtils.getId(entityType.getDocConceptKey()), ValidationStatus.INVALID,
217 "ancestor of itself");
220 return parentEntityTypeKey;
224 * validate all the ancestors of an entity type.
226 * @param entityTypes the set of entity types that exist
227 * @param result the result of the ancestor search with any warnings or errors
229 private static void validEntityTypeAncestors(Map<String, ? extends DocToscaEntity<?>> entityTypes,
230 Set<String> reference, final BeanValidationResult result) {
231 if (entityTypes != null) {
232 for (var entityType : entityTypes.values()) {
233 var parentEntityTypeKey = extractDerivedFrom(entityType, result);
234 if (parentEntityTypeKey == null) {
237 if (!isTypePresent(parentEntityTypeKey, reference)) {
238 result.addResult("parent", parentEntityTypeKey, ValidationStatus.INVALID, NOT_FOUND);
245 * validate all the ancestors of an entity type.
247 * @param entityTypesList the set of entity types that exist
248 * @param result the result of the ancestor search with any warnings or errors
250 private static <T extends DocToscaEntity<?>> void validEntityTypeAncestors(List<Map<String, T>> entityTypesList,
251 Set<String> reference, final BeanValidationResult result) {
252 if (entityTypesList != null) {
253 for (var entityTypes : entityTypesList) {
254 for (var entityType : entityTypes.values()) {
255 var parentEntityTypeKey = extractDerivedFrom(entityType, result);
256 if (parentEntityTypeKey == null) {
259 if (!isTypePresent(parentEntityTypeKey, reference)) {
260 result.addResult("parent", parentEntityTypeKey, ValidationStatus.INVALID, NOT_FOUND);