0053ca0ca38b79225f5158966ea225d14da7c56e
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2022-2023 Nordix Foundation.
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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.clamp.models.acm.document.base;
22
23 import java.util.Collection;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
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.Validated;
36
37 @NoArgsConstructor(access = AccessLevel.PRIVATE)
38 public final class ToscaServiceTemplateValidation {
39
40     private static final String ROOT_KEY_NAME_SUFFIX = ".Root";
41     private static final String TOPOLOGY_TEMPLATE = "TopologyTemplate";
42
43     /**
44      * validate a serviceTemplate.
45      *
46      * @param result the result
47      * @param serviceTemplate the serviceTemplate to validate
48      */
49     public static void validate(final BeanValidationResult result, DocToscaServiceTemplate serviceTemplate,
50                                 String toscaCompositionName) {
51
52         var references = DocUtil.getToscaReferences(serviceTemplate);
53
54         validEntityTypeAncestors(serviceTemplate.getDataTypes(), references.get(DocUtil.REF_DATA_TYPES), result);
55         validEntityTypeAncestors(serviceTemplate.getCapabilityTypes(), references.get(DocUtil.REF_CAPABILITY_TYPES),
56                 result);
57         validEntityTypeAncestors(serviceTemplate.getNodeTypes(), references.get(DocUtil.REF_NODE_TYPES), result);
58         validEntityTypeAncestors(serviceTemplate.getRelationshipTypes(), references.get(DocUtil.REF_RELATIONSHIP_TYPES),
59                 result);
60         validEntityTypeAncestors(serviceTemplate.getPolicyTypes(), references.get(DocUtil.REF_POLICY_TYPES), result);
61
62         if (serviceTemplate.getNodeTypes() != null) {
63             for (var nodeType : serviceTemplate.getNodeTypes().values()) {
64                 validEntityTypeAncestors(nodeType.getRequirements(), references.get(DocUtil.REF_REQUIREMENTS), result);
65             }
66         }
67
68         validateToscaTopologyTemplate(result, serviceTemplate.getToscaTopologyTemplate(), toscaCompositionName);
69
70         if (serviceTemplate.getToscaTopologyTemplate() != null) {
71             validEntityTypeAncestors(serviceTemplate.getToscaTopologyTemplate().getNodeTemplates(),
72                     references.get(DocUtil.REF_NODE_TEMPLATES), result);
73             validEntityTypeAncestors(serviceTemplate.getToscaTopologyTemplate().getPolicies(),
74                     references.get(DocUtil.REF_POLICIES), result);
75
76             if (serviceTemplate.getToscaTopologyTemplate().getNodeTemplates() != null) {
77                 for (var nodeTemplate : serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().values()) {
78                     validEntityTypeAncestors(nodeTemplate.getCapabilities(), references.get(DocUtil.REF_CAPABILITIES),
79                             result);
80                     validEntityTypeAncestors(nodeTemplate.getRequirements(), references.get(DocUtil.REF_REQUIREMENTS),
81                             result);
82                 }
83             }
84         }
85
86         validateReferencedDataTypes(result, serviceTemplate, references);
87
88         validatePolicyTypesInPolicies(result, serviceTemplate, references);
89
90     }
91
92     /**
93      * Validate ToscaTopologyTemplate.
94      *
95      * @param result the BeanValidationResult
96      * @param topologyTemplate the ToscaServiceTemplate
97      * @param toscaCompositionName the name of the ToscaComposition
98      */
99     public static void validateToscaTopologyTemplate(BeanValidationResult result,
100             DocToscaTopologyTemplate topologyTemplate, String toscaCompositionName) {
101         String acNodeTypeNotPresent =
102                 "NodeTemplate with type " + toscaCompositionName + " must exist!";
103
104         if (topologyTemplate != null && topologyTemplate.getNodeTemplates() != null) {
105             var nodeTemplates = topologyTemplate.getNodeTemplates();
106             var acNumber = nodeTemplates.values().stream().filter(
107                     nodeTemplate -> toscaCompositionName.equals(nodeTemplate.getType()))
108                     .count();
109             if (acNumber == 0) {
110                 result.addResult(TOPOLOGY_TEMPLATE, nodeTemplates, ValidationStatus.INVALID, acNodeTypeNotPresent);
111             }
112             if (acNumber > 1) {
113                 result.addResult(TOPOLOGY_TEMPLATE, nodeTemplates, ValidationStatus.INVALID, "NodeTemplate with type "
114                         + toscaCompositionName + " not allowed to be more than one!");
115             }
116         } else {
117             result.addResult(TOPOLOGY_TEMPLATE, topologyTemplate, ValidationStatus.INVALID, acNodeTypeNotPresent);
118         }
119     }
120
121     /**
122      * Validate that all data types referenced in policy types exist.
123      *
124      * @param result where the results are added
125      */
126     private static void validateReferencedDataTypes(final BeanValidationResult result,
127             DocToscaServiceTemplate serviceTemplate, Map<String, Set<String>> references) {
128         if (serviceTemplate.getDataTypes() != null) {
129             for (var dataType : serviceTemplate.getDataTypes().values()) {
130                 validateReferencedDataTypesExists(result, dataType.getReferencedDataTypes(), references);
131             }
132         }
133
134         if (serviceTemplate.getPolicyTypes() != null) {
135             for (var policyType : serviceTemplate.getPolicyTypes().values()) {
136                 validateReferencedDataTypesExists(result, policyType.getReferencedDataTypes(), references);
137             }
138         }
139         if (serviceTemplate.getNodeTypes() != null) {
140             for (var nodeType : serviceTemplate.getNodeTypes().values()) {
141                 validateReferencedDataTypesExists(result, nodeType.getReferencedDataTypes(), references);
142             }
143         }
144     }
145
146     /**
147      * Validate that the referenced data types exist for a collection of data type keys.
148      *
149      * @param dataTypeKeyCollection the data type key collection
150      * @param result where the results are added
151      */
152     private static void validateReferencedDataTypesExists(final BeanValidationResult result,
153             final Collection<DocConceptKey> dataTypeKeyCollection, Map<String, Set<String>> references) {
154         for (DocConceptKey dataTypeKey : dataTypeKeyCollection) {
155             if (!isTypePresent(dataTypeKey, references.get(DocUtil.REF_DATA_TYPES))) {
156                 result.addResult("data type", dataTypeKey.getId(), ValidationStatus.INVALID, Validated.NOT_FOUND);
157             }
158         }
159     }
160
161     /**
162      * Validate that all policy types referenced in policies exist.
163      *
164      * @param result where the results are added
165      */
166     private static void validatePolicyTypesInPolicies(final BeanValidationResult result,
167             DocToscaServiceTemplate serviceTemplate, Map<String, Set<String>> references) {
168         if (serviceTemplate.getToscaTopologyTemplate() == null) {
169             return;
170         }
171
172         if (serviceTemplate.getToscaTopologyTemplate().getPolicies() != null) {
173             for (var policy : serviceTemplate.getToscaTopologyTemplate().getPolicies().values()) {
174                 var key = policy.getTypeDocConceptKey();
175                 if (!isTypePresent(key, references.get(DocUtil.REF_POLICY_TYPES))) {
176                     result.addResult("policy type", key, ValidationStatus.INVALID, Validated.NOT_FOUND);
177                 }
178             }
179         }
180         if (serviceTemplate.getToscaTopologyTemplate().getNodeTemplates() != null) {
181             for (var nodeTemplate : serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().values()) {
182                 var key = nodeTemplate.getTypeDocConceptKey();
183                 if (!isTypePresent(key, references.get(DocUtil.REF_NODE_TYPES))) {
184                     result.addResult("node Template", key, ValidationStatus.INVALID, Validated.NOT_FOUND);
185                 }
186             }
187         }
188     }
189
190     private static boolean isTypePresent(String key, Set<String> reference) {
191         if (reference == null || reference.isEmpty()) {
192             return false;
193         }
194         return reference.contains(key);
195     }
196
197     private static boolean isTypePresent(DocConceptKey key, Set<String> reference) {
198         if (reference == null || reference.isEmpty()) {
199             return false;
200         }
201         return reference.contains(key.getId());
202     }
203
204     private static String extractDerivedFrom(DocToscaEntity<?> entityType, final BeanValidationResult result) {
205         if (entityType.getDerivedFrom() == null) {
206             return null;
207         }
208         var parentEntityTypeKey = entityType.getDerivedFrom();
209
210         if (parentEntityTypeKey.endsWith(ROOT_KEY_NAME_SUFFIX)) {
211             return null;
212         }
213         if (entityType.getName().equals(parentEntityTypeKey)) {
214             result.addResult("entity type", entityType.getDocConceptKey().getId(), ValidationStatus.INVALID,
215                     "ancestor of itself");
216             return null;
217         }
218         return parentEntityTypeKey;
219     }
220
221     /**
222      * validate all the ancestors of an entity type.
223      *
224      * @param entityTypes the set of entity types that exist
225      * @param result the result of the ancestor search with any warnings or errors
226      */
227     private static void validEntityTypeAncestors(Map<String, ? extends DocToscaEntity<?>> entityTypes,
228             Set<String> reference, @NonNull final BeanValidationResult result) {
229         if (entityTypes != null) {
230             for (var entityType : entityTypes.values()) {
231                 var parentEntityTypeKey = extractDerivedFrom(entityType, result);
232                 if (parentEntityTypeKey == null) {
233                     continue;
234                 }
235                 if (!isTypePresent(parentEntityTypeKey, reference)) {
236                     result.addResult("parent", parentEntityTypeKey, ValidationStatus.INVALID, Validated.NOT_FOUND);
237                 }
238             }
239         }
240     }
241
242     /**
243      * validate all the ancestors of an entity type.
244      *
245      * @param entityTypesList the set of entity types that exist
246      * @param result the result of the ancestor search with any warnings or errors
247      */
248     private static <T extends DocToscaEntity<?>> void validEntityTypeAncestors(List<Map<String, T>> entityTypesList,
249             Set<String> reference, @NonNull final BeanValidationResult result) {
250         if (entityTypesList != null) {
251             for (var entityTypes : entityTypesList) {
252                 for (var entityType : entityTypes.values()) {
253                     var parentEntityTypeKey = extractDerivedFrom(entityType, result);
254                     if (parentEntityTypeKey == null) {
255                         continue;
256                     }
257                     if (!isTypePresent(parentEntityTypeKey, reference)) {
258                         result.addResult("parent", parentEntityTypeKey, ValidationStatus.INVALID, Validated.NOT_FOUND);
259                     }
260                 }
261             }
262         }
263     }
264
265 }