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