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