push addional code
[sdc.git] / openecomp-be / lib / openecomp-tosca-lib / src / main / java / org / openecomp / sdc / tosca / services / impl / ToscaAnalyzerServiceImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.sdc.tosca.services.impl;
22
23 import org.apache.commons.collections4.CollectionUtils;
24 import org.apache.commons.collections4.MapUtils;
25 import org.openecomp.core.utilities.CommonMethods;
26 import org.openecomp.sdc.common.errors.CoreException;
27 import org.openecomp.sdc.tosca.datatypes.ToscaCapabilityType;
28 import org.openecomp.sdc.tosca.datatypes.ToscaElementTypes;
29 import org.openecomp.sdc.tosca.datatypes.ToscaNodeType;
30 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
31 import org.openecomp.sdc.tosca.datatypes.model.CapabilityType;
32 import org.openecomp.sdc.tosca.datatypes.model.Import;
33 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
34 import org.openecomp.sdc.tosca.datatypes.model.NodeType;
35 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
36 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
37 import org.openecomp.sdc.tosca.errors.ToscaInvalidEntryNotFoundErrorBuilder;
38 import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder;
39 import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstitutionServiceTemplateErrorBuilder;
40 import org.openecomp.sdc.tosca.errors.ToscaNodeTypeNotFoundErrorBuilder;
41 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
42 import org.openecomp.sdc.tosca.services.ToscaConstants;
43 import org.openecomp.sdc.tosca.services.yamlutil.ToscaExtensionYamlUtil;
44
45 import java.util.ArrayList;
46 import java.util.HashMap;
47 import java.util.HashSet;
48 import java.util.List;
49 import java.util.Map;
50 import java.util.Objects;
51 import java.util.Optional;
52 import java.util.Set;
53
54 public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
55   /*
56   node template with type equal to node type or derived from node type.
57    */
58   @Override
59   public Map<String, NodeTemplate> getNodeTemplatesByType(ServiceTemplate serviceTemplate,
60                                                           String nodeType,
61                                                           ToscaServiceModel toscaServiceModel) {
62     Map<String, NodeTemplate> nodeTemplates = new HashMap<>();
63
64     if (Objects.nonNull(serviceTemplate.getTopology_template())
65         && MapUtils.isNotEmpty(serviceTemplate.getTopology_template().getNode_templates())) {
66       for (Map.Entry<String, NodeTemplate> nodeTemplateEntry : serviceTemplate
67           .getTopology_template().getNode_templates().entrySet()) {
68         if (isTypeOf(nodeTemplateEntry.getValue(), nodeType, serviceTemplate, toscaServiceModel)) {
69           nodeTemplates.put(nodeTemplateEntry.getKey(), nodeTemplateEntry.getValue());
70         }
71
72       }
73     }
74     return nodeTemplates;
75   }
76
77   @Override
78   public boolean isTypeOf(NodeTemplate nodeTemplate, String nodeType,
79                           ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
80     if (nodeTemplate == null) {
81       return false;
82     }
83
84     if (isNodeTemplateOfTypeNodeType(nodeTemplate, nodeType)) {
85       return true;
86     }
87
88     Optional<Boolean> nodeTypeExistInServiceTemplateHierarchy =
89         isNodeTypeExistInServiceTemplateHierarchy(nodeType, nodeTemplate.getType(), serviceTemplate,
90             toscaServiceModel, null);
91     return nodeTypeExistInServiceTemplateHierarchy.orElseThrow(() -> new CoreException(
92         new ToscaNodeTypeNotFoundErrorBuilder(nodeTemplate.getType()).build()));
93   }
94
95
96   private Optional<Boolean> isNodeTypeExistInServiceTemplateHierarchy(String nodeTypeToMatch,
97                                                                String nodeTypeToSearch,
98                                                                ServiceTemplate serviceTemplate,
99                                                                ToscaServiceModel toscaServiceModel,
100                                                                Set<String> analyzedImportFiles) {
101     Map<String, NodeType> searchableNodeTypes = serviceTemplate.getNode_types();
102     if (!MapUtils.isEmpty(searchableNodeTypes)) {
103       NodeType nodeType = searchableNodeTypes.get(nodeTypeToSearch);
104       if (Objects.nonNull(nodeType)) {
105         if (Objects.equals(nodeType.getDerived_from(), nodeTypeToMatch)) {
106           return Optional.of(true);
107         } else if (isNodeTypeIsToscaRoot(nodeType)) {
108           return Optional.of(false);
109         } else {
110           return isNodeTypeExistInServiceTemplateHierarchy(nodeTypeToMatch,
111               nodeType.getDerived_from(), serviceTemplate, toscaServiceModel, null);
112         }
113       } else {
114         return isNodeTypeExistInImports(nodeTypeToMatch, nodeTypeToSearch, serviceTemplate,
115             toscaServiceModel, analyzedImportFiles);
116       }
117     }
118     return isNodeTypeExistInImports(nodeTypeToMatch, nodeTypeToSearch, serviceTemplate,
119         toscaServiceModel, analyzedImportFiles);
120
121   }
122
123   private Optional<Boolean> isNodeTypeExistInImports(String nodeTypeToMatch,
124                                                      String nodeTypeToSearch,
125                                                      ServiceTemplate serviceTemplate,
126                                                      ToscaServiceModel toscaServiceModel,
127                                                      Set<String> analyzedImportFiles) {
128     Map<String, Import> imports = serviceTemplate.getImports();
129     if (imports == null) {
130       return Optional.empty();
131     }
132
133     analyzedImportFiles = createAnalyzedImportFilesSet(analyzedImportFiles);
134     for (Import anImport : imports.values()) {
135       if (Objects.isNull(anImport) || Objects.isNull(anImport.getFile())) {
136         throw new RuntimeException("import without file entry");
137       }
138       String importFile = anImport.getFile();
139       if (analyzedImportFiles.contains(importFile)) {
140         continue;
141       }
142       addImportFileToAnalyzedImportFilesSet(analyzedImportFiles, importFile);
143       ServiceTemplate template = toscaServiceModel.getServiceTemplates().get(importFile);
144       Optional<Boolean> nodeTypeExistInServiceTemplateHierarchy =
145           isNodeTypeExistInServiceTemplateHierarchy(nodeTypeToMatch, nodeTypeToSearch, template,
146               toscaServiceModel, analyzedImportFiles);
147       if (nodeTypeExistInServiceTemplateHierarchy.isPresent()) {
148         if (nodeTypeExistInServiceTemplateHierarchy.get()) {
149           return Optional.of(true);
150         }
151       }
152     }
153     return Optional.of(false);
154   }
155
156   private Set<String> addImportFileToAnalyzedImportFilesSet(Set<String> analyzedImportFiles,
157                                                             String importFile) {
158     analyzedImportFiles.add(importFile);
159     return analyzedImportFiles;
160   }
161
162   private Set<String> createAnalyzedImportFilesSet(Set<String> analyzedImportFiles) {
163     if (Objects.isNull(analyzedImportFiles)) {
164       analyzedImportFiles = new HashSet<>();
165     }
166     return analyzedImportFiles;
167   }
168
169   private boolean isNodeTypeIsToscaRoot(NodeType stNodeType) {
170     return Objects.equals(stNodeType.getDerived_from(), ToscaNodeType.ROOT.getDisplayName());
171   }
172
173   private boolean isNodeTemplateOfTypeNodeType(NodeTemplate nodeTemplate, String nodeType) {
174     return Objects.equals(nodeTemplate.getType(), nodeType);
175   }
176
177   @Override
178   public List<RequirementAssignment> getRequirements(NodeTemplate nodeTemplate,
179                                                      String requirementId) {
180     List<RequirementAssignment> requirements = new ArrayList<>();
181     List<Map<String, RequirementAssignment>> requirementList = nodeTemplate.getRequirements();
182     if (requirementList != null) {
183       requirementList.stream().filter(reqMap -> reqMap.get(requirementId) != null)
184           .forEach(reqMap -> {
185             ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
186             RequirementAssignment reqAssignment = toscaExtensionYamlUtil
187                 .yamlToObject(toscaExtensionYamlUtil.objectToYaml(reqMap.get(requirementId)),
188                     RequirementAssignment.class);
189             requirements.add(reqAssignment);
190           });
191     }
192     return requirements;
193   }
194
195   @Override
196   public Optional<NodeTemplate> getNodeTemplateById(ServiceTemplate serviceTemplate,
197                                                     String nodeTemplateId) {
198     if ((serviceTemplate.getTopology_template() != null)
199         && (serviceTemplate.getTopology_template().getNode_templates() != null)
200         && (serviceTemplate.getTopology_template().getNode_templates()
201         .get(nodeTemplateId) != null)) {
202       return Optional
203           .of(serviceTemplate.getTopology_template().getNode_templates().get(nodeTemplateId));
204     }
205     return Optional.empty();
206   }
207
208   @Override
209   public Optional<String> getSubstituteServiceTemplateName(String substituteNodeTemplateId,
210                                                            NodeTemplate substitutableNodeTemplate) {
211     if (!isSubstitutableNodeTemplate(substitutableNodeTemplate)) {
212       return Optional.empty();
213     }
214
215     if (substitutableNodeTemplate.getProperties() != null
216         && substitutableNodeTemplate.getProperties()
217             .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME) != null) {
218       Object serviceTemplateFilter = substitutableNodeTemplate.getProperties()
219           .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
220       if (serviceTemplateFilter != null && serviceTemplateFilter instanceof Map) {
221         Object substituteServiceTemplate = ((Map) serviceTemplateFilter)
222             .get(ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME);
223         if (substituteServiceTemplate == null) {
224           throw new CoreException(
225               new ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder(substituteNodeTemplateId)
226                   .build());
227         }
228         return Optional.of(substituteServiceTemplate.toString());
229       }
230     }
231     throw new CoreException(
232         new ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder(substituteNodeTemplateId)
233             .build());
234   }
235
236   @Override
237   public Map<String, NodeTemplate> getSubstitutableNodeTemplates(ServiceTemplate serviceTemplate) {
238     Map<String, NodeTemplate> substitutableNodeTemplates = new HashMap<>();
239
240     if (serviceTemplate == null
241         || serviceTemplate.getTopology_template() == null
242         || serviceTemplate.getTopology_template().getNode_templates() == null) {
243       return substitutableNodeTemplates;
244     }
245
246     Map<String, NodeTemplate> nodeTemplates =
247         serviceTemplate.getTopology_template().getNode_templates();
248     for (String nodeTemplateId : nodeTemplates.keySet()) {
249       NodeTemplate nodeTemplate = nodeTemplates.get(nodeTemplateId);
250       if (isSubstitutableNodeTemplate(nodeTemplate)) {
251         substitutableNodeTemplates.put(nodeTemplateId, nodeTemplate);
252       }
253     }
254
255     return substitutableNodeTemplates;
256   }
257
258   private boolean isSubstitutableNodeTemplate(NodeTemplate nodeTemplate) {
259     return nodeTemplate.getDirectives() != null
260         && nodeTemplate.getDirectives().contains(ToscaConstants
261         .NODE_TEMPLATE_DIRECTIVE_SUBSTITUTABLE);
262   }
263
264   private boolean isSubstitutionServiceTemplate(String substituteServiceTemplateFileName,
265                                                 ServiceTemplate substituteServiceTemplate) {
266     if (substituteServiceTemplate != null
267         && substituteServiceTemplate.getTopology_template() != null
268         && substituteServiceTemplate.getTopology_template().getSubstitution_mappings() != null) {
269       if (substituteServiceTemplate.getTopology_template().getSubstitution_mappings()
270           .getNode_type() == null) {
271         throw new CoreException(new ToscaInvalidSubstitutionServiceTemplateErrorBuilder(
272             substituteServiceTemplateFileName).build());
273       }
274       return true;
275     }
276     return false;
277
278   }
279
280   @Override
281   public Optional<Map.Entry<String, NodeTemplate>> getSubstitutionMappedNodeTemplateByExposedReq(
282       String substituteServiceTemplateFileName, ServiceTemplate substituteServiceTemplate,
283       String requirementId) {
284     if (isSubstitutionServiceTemplate(substituteServiceTemplateFileName,
285         substituteServiceTemplate)) {
286       Map<String, List<String>> substitutionMappingRequirements =
287           substituteServiceTemplate.getTopology_template().getSubstitution_mappings()
288               .getRequirements();
289       if (substitutionMappingRequirements != null) {
290         List<String> requirementMapping = substitutionMappingRequirements.get(requirementId);
291         if (requirementMapping != null && !requirementMapping.isEmpty()) {
292           String mappedNodeTemplateId = requirementMapping.get(0);
293           Optional<NodeTemplate> mappedNodeTemplate =
294               getNodeTemplateById(substituteServiceTemplate, mappedNodeTemplateId);
295           mappedNodeTemplate.orElseThrow(() -> new CoreException(
296               new ToscaInvalidEntryNotFoundErrorBuilder("Node Template", mappedNodeTemplateId)
297                   .build()));
298           Map.Entry<String, NodeTemplate> mappedNodeTemplateEntry =
299               new Map.Entry<String, NodeTemplate>() {
300                 @Override
301                 public String getKey() {
302                   return mappedNodeTemplateId;
303                 }
304
305                 @Override
306                 public NodeTemplate getValue() {
307                   return mappedNodeTemplate.get();
308                 }
309
310                 @Override
311                 public NodeTemplate setValue(NodeTemplate value) {
312                   return null;
313                 }
314               };
315           return Optional.of(mappedNodeTemplateEntry);
316         }
317       }
318     }
319     return Optional.empty();
320   }
321
322
323   /*
324   match only for the input which is not null
325    */
326   @Override
327   public boolean isDesiredRequirementAssignment(RequirementAssignment requirementAssignment,
328                                                 String capability, String node,
329                                                 String relationship) {
330     if (capability != null) {
331       if (requirementAssignment.getCapability() == null
332           || !requirementAssignment.getCapability().equals(capability)) {
333         return false;
334       }
335     }
336
337     if (node != null) {
338       if (requirementAssignment.getNode() == null
339           || !requirementAssignment.getNode().equals(node)) {
340         return false;
341       }
342     }
343
344     if (relationship != null) {
345       if (requirementAssignment.getRelationship() == null
346           || !requirementAssignment.getRelationship().equals(relationship)) {
347         return false;
348       }
349     }
350
351     return !(capability == null && node == null && relationship == null);
352
353   }
354
355   @Override
356   public Object getFlatEntity(ToscaElementTypes elementType, String typeId,
357                               ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel) {
358     Object returnEntity;
359
360     switch (elementType) {
361       case CAPABILITY_TYPE:
362         returnEntity = new CapabilityType();
363         break;
364       default:
365         throw new RuntimeException(
366             "Entity[" + elementType + "] id[" + typeId + "] flat not supported");
367     }
368
369     scanAnFlatEntity(elementType, typeId, returnEntity, serviceTemplate, toscaModel);
370
371
372     return returnEntity;
373   }
374
375   private void scanAnFlatEntity(ToscaElementTypes elementType, String typeId, Object entity,
376                                 ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel) {
377
378
379     boolean entityFound =
380         enrichEntityFromCurrentServiceTemplate(elementType, typeId, entity, serviceTemplate,
381             toscaModel);
382     if (!entityFound) {
383       Map<String, Import> imports = serviceTemplate.getImports();
384       if (MapUtils.isEmpty(imports)) {
385         return;
386       }
387       for (Import importServiceTemplate : imports.values()) {
388         ServiceTemplate template =
389             toscaModel.getServiceTemplates().get(importServiceTemplate.getFile());
390         scanAnFlatEntity(elementType, typeId, entity, template, toscaModel);
391       }
392     }
393
394
395   }
396
397   private boolean enrichEntityFromCurrentServiceTemplate(ToscaElementTypes elementType,
398                                                          String typeId, Object entity,
399                                                          ServiceTemplate serviceTemplate,
400                                                          ToscaServiceModel toscaModel) {
401     String derivedFrom;
402     switch (elementType) {
403       case CAPABILITY_TYPE:
404         if (serviceTemplate.getCapability_types() != null
405             && serviceTemplate.getCapability_types().containsKey(typeId)) {
406
407           CapabilityType targetCapabilityType = ((CapabilityType) entity);
408           CapabilityType sourceCapabilityType = serviceTemplate.getCapability_types().get(typeId);
409           derivedFrom = sourceCapabilityType.getDerived_from();
410           if (derivedFrom != null
411               && !ToscaCapabilityType.NFV_METRIC.getDisplayName().equals(derivedFrom)) {
412             scanAnFlatEntity(elementType, derivedFrom, entity, serviceTemplate, toscaModel);
413           }
414           combineCapabilityTypeInfo(sourceCapabilityType, targetCapabilityType);
415         } else {
416           return false;
417         }
418         break;
419       default:
420         throw new RuntimeException(
421             "Entity[" + elementType + "] id[" + typeId + "] flat not supported");
422     }
423
424     return true;
425
426
427   }
428
429   private void combineCapabilityTypeInfo(CapabilityType sourceCapabilityType,
430                                          CapabilityType targetCapabilityType) {
431     if (MapUtils.isNotEmpty(sourceCapabilityType.getAttributes())) {
432       if (targetCapabilityType.getAttributes() == null) {
433         targetCapabilityType.setAttributes(new HashMap<>());
434       }
435       targetCapabilityType.getAttributes().putAll(sourceCapabilityType.getAttributes());
436     }
437
438     if (MapUtils.isNotEmpty(sourceCapabilityType.getProperties())) {
439       if (targetCapabilityType.getProperties() == null) {
440         targetCapabilityType.setProperties(new HashMap<>());
441       }
442       targetCapabilityType.getProperties().putAll(sourceCapabilityType.getProperties());
443     }
444
445     if (CollectionUtils.isNotEmpty(sourceCapabilityType.getValid_source_types())) {
446       if (targetCapabilityType.getValid_source_types() == null) {
447         targetCapabilityType.setValid_source_types(new ArrayList<>());
448       }
449       targetCapabilityType.getValid_source_types()
450           .addAll(sourceCapabilityType.getValid_source_types());
451     }
452
453     if (CommonMethods.isEmpty(sourceCapabilityType.getDerived_from())) {
454       targetCapabilityType.setDerived_from(sourceCapabilityType.getDerived_from());
455     }
456     if (CommonMethods.isEmpty(sourceCapabilityType.getDescription())) {
457       targetCapabilityType.setDescription(sourceCapabilityType.getDescription());
458     }
459     if (CommonMethods.isEmpty(sourceCapabilityType.getVersion())) {
460       targetCapabilityType.setVersion(sourceCapabilityType.getVersion());
461     }
462
463
464   }
465
466
467 }