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