898025c44dd19fcb755daaeeb36a58442ab01a8c
[sdc.git] /
1 /*
2  * Copyright © 2016-2017 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdc.tosca.services.impl;
18
19 import org.apache.commons.collections4.CollectionUtils;
20 import org.apache.commons.collections4.MapUtils;
21 import org.apache.commons.lang3.StringUtils;
22 import org.openecomp.core.utilities.CommonMethods;
23 import org.openecomp.sdc.common.errors.CoreException;
24 import org.openecomp.sdc.datatypes.error.ErrorLevel;
25 import org.openecomp.sdc.logging.context.impl.MdcDataErrorMessage;
26 import org.openecomp.sdc.logging.types.LoggerConstants;
27 import org.openecomp.sdc.logging.types.LoggerErrorCode;
28 import org.openecomp.sdc.logging.types.LoggerErrorDescription;
29 import org.openecomp.sdc.logging.types.LoggerTragetServiceName;
30 import org.openecomp.sdc.tosca.datatypes.ToscaElementTypes;
31 import org.openecomp.sdc.tosca.datatypes.ToscaNodeType;
32 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
33 import org.openecomp.sdc.tosca.datatypes.model.AttributeDefinition;
34 import org.openecomp.sdc.tosca.datatypes.model.CapabilityDefinition;
35 import org.openecomp.sdc.tosca.datatypes.model.CapabilityType;
36 import org.openecomp.sdc.tosca.datatypes.model.Import;
37 import org.openecomp.sdc.tosca.datatypes.model.NodeTemplate;
38 import org.openecomp.sdc.tosca.datatypes.model.NodeType;
39 import org.openecomp.sdc.tosca.datatypes.model.ParameterDefinition;
40 import org.openecomp.sdc.tosca.datatypes.model.PropertyDefinition;
41 import org.openecomp.sdc.tosca.datatypes.model.PropertyType;
42 import org.openecomp.sdc.tosca.datatypes.model.RequirementAssignment;
43 import org.openecomp.sdc.tosca.datatypes.model.RequirementDefinition;
44 import org.openecomp.sdc.tosca.datatypes.model.ServiceTemplate;
45 import org.openecomp.sdc.tosca.errors.ToscaInvalidEntryNotFoundErrorBuilder;
46 import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder;
47 import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstitutionServiceTemplateErrorBuilder;
48 import org.openecomp.sdc.tosca.errors.ToscaNodeTypeNotFoundErrorBuilder;
49 import org.openecomp.sdc.tosca.services.DataModelUtil;
50 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
51 import org.openecomp.sdc.tosca.services.ToscaConstants;
52 import org.openecomp.sdc.tosca.services.ToscaExtensionYamlUtil;
53 import org.openecomp.sdc.tosca.services.ToscaUtil;
54
55 import java.util.ArrayList;
56 import java.util.Collection;
57 import java.util.Collections;
58 import java.util.HashMap;
59 import java.util.HashSet;
60 import java.util.List;
61 import java.util.Map;
62 import java.util.Objects;
63 import java.util.Optional;
64 import java.util.Set;
65
66 public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
67
68   @Override
69   public List<Map<String, RequirementDefinition>> calculateExposedRequirements(
70       List<Map<String, RequirementDefinition>> nodeTypeRequirementsDefinitionList,
71       Map<String, RequirementAssignment> nodeTemplateRequirementsAssignment) {
72
73     if (nodeTypeRequirementsDefinitionList == null) {
74       return Collections.emptyList();
75     }
76     for (Map.Entry<String, RequirementAssignment> entry : nodeTemplateRequirementsAssignment
77         .entrySet()) {
78       if (entry.getValue().getNode() != null) {
79         Optional<RequirementDefinition> requirementDefinition =
80             DataModelUtil.getRequirementDefinition(nodeTypeRequirementsDefinitionList, entry
81                 .getKey());
82         RequirementDefinition cloneRequirementDefinition;
83         if (requirementDefinition.isPresent()) {
84           cloneRequirementDefinition = requirementDefinition.get().clone();
85           updateRequirementDefinition(nodeTypeRequirementsDefinitionList, entry,
86               cloneRequirementDefinition);
87         }
88       } else {
89         for (Map<String, RequirementDefinition> nodeTypeRequirementsMap :
90             nodeTypeRequirementsDefinitionList) {
91           updateMinMaxOccurencesForNodeTypeRequirement(entry, nodeTypeRequirementsMap);
92         }
93       }
94     }
95     return nodeTypeRequirementsDefinitionList;
96   }
97
98   private void updateMinMaxOccurencesForNodeTypeRequirement(
99       Map.Entry<String, RequirementAssignment> entry,
100       Map<String, RequirementDefinition> nodeTypeRequirementsMap) {
101     Object max = nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences() != null
102         && nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences().length > 0
103         ? nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences()[1] : 1;
104     Object min = nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences() != null
105         && nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences().length > 0
106         ? nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences()[0] : 1;
107     nodeTypeRequirementsMap.get(entry.getKey()).setOccurrences(new Object[]{min, max});
108   }
109
110   private void updateRequirementDefinition(
111       List<Map<String, RequirementDefinition>> nodeTypeRequirementsDefinitionList,
112       Map.Entry<String, RequirementAssignment> entry,
113       RequirementDefinition cloneRequirementDefinition) {
114     if (!evaluateRequirementFulfillment(cloneRequirementDefinition)) {
115       CommonMethods.mergeEntryInList(entry.getKey(), cloneRequirementDefinition,
116           nodeTypeRequirementsDefinitionList);
117     } else {
118       DataModelUtil.removeRequirementsDefinition(nodeTypeRequirementsDefinitionList, entry
119           .getKey());
120     }
121   }
122
123   private static boolean evaluateRequirementFulfillment(RequirementDefinition
124                                                             requirementDefinition) {
125     Object[] occurrences = requirementDefinition.getOccurrences();
126     if (occurrences == null) {
127       requirementDefinition.setOccurrences(new Object[]{1, 1});
128       return false;
129     }
130     if (occurrences[1].equals(ToscaConstants.UNBOUNDED)) {
131       return false;
132     }
133
134     if (occurrences[1].equals(1)) {
135       return true;
136     }
137     occurrences[1] = (Integer) occurrences[1] - 1;
138     return false;
139   }
140
141   @Override
142   public Map<String, CapabilityDefinition> calculateExposedCapabilities(
143       Map<String, CapabilityDefinition> nodeTypeCapabilitiesDefinition,
144       Map<String, Map<String, RequirementAssignment>> fullFilledRequirementsDefinitionMap) {
145
146     String capabilityKey;
147     String capability;
148     String node;
149     for (Map.Entry<String, Map<String, RequirementAssignment>> entry :
150         fullFilledRequirementsDefinitionMap.entrySet()) {
151       for (Map.Entry<String, RequirementAssignment> fullFilledEntry : entry.getValue().entrySet()) {
152
153         capability = fullFilledEntry.getValue().getCapability();
154         fullFilledEntry.getValue().getOccurrences();
155         node = fullFilledEntry.getValue().getNode();
156         capabilityKey = capability + "_" + node;
157         CapabilityDefinition capabilityDefinition = nodeTypeCapabilitiesDefinition.get(
158             capabilityKey);
159         if (capabilityDefinition != null) {
160           CapabilityDefinition clonedCapabilityDefinition = capabilityDefinition.clone();
161           nodeTypeCapabilitiesDefinition.put(capabilityKey, capabilityDefinition.clone());
162           updateNodeTypeCapabilitiesDefinition(nodeTypeCapabilitiesDefinition, capabilityKey,
163               clonedCapabilityDefinition);
164         }
165       }
166     }
167
168     Map<String, CapabilityDefinition> exposedCapabilitiesDefinition = new HashMap<>();
169     for (Map.Entry<String, CapabilityDefinition> entry : nodeTypeCapabilitiesDefinition
170         .entrySet()) {
171       exposedCapabilitiesDefinition.put(entry.getKey(), entry.getValue());
172     }
173     return exposedCapabilitiesDefinition;
174   }
175
176   private void updateNodeTypeCapabilitiesDefinition(
177       Map<String, CapabilityDefinition> nodeTypeCapabilitiesDefinition, String capabilityKey,
178       CapabilityDefinition clonedCapabilityDefinition) {
179     if (evaluateCapabilityFulfillment(clonedCapabilityDefinition)) {
180       nodeTypeCapabilitiesDefinition.remove(capabilityKey);
181     } else {
182       nodeTypeCapabilitiesDefinition.put(capabilityKey, clonedCapabilityDefinition);
183     }
184   }
185
186   private static boolean evaluateCapabilityFulfillment(CapabilityDefinition capabilityDefinition) {
187
188     Object[] occurrences = capabilityDefinition.getOccurrences();
189     if (occurrences == null) {
190       capabilityDefinition.setOccurrences(new Object[]{1, ToscaConstants.UNBOUNDED});
191       return false;
192     }
193     if (occurrences[1].equals(ToscaConstants.UNBOUNDED)) {
194       return false;
195     }
196
197     if (occurrences[1].equals(1)) {
198       return true;
199     }
200     occurrences[1] = (Integer) occurrences[1] - 1;
201     return false;
202   }
203
204   /*
205     node template with type equal to node type or derived from node type
206      */
207   @Override
208   public Map<String, NodeTemplate> getNodeTemplatesByType(ServiceTemplate serviceTemplate,
209                                                           String nodeType,
210                                                           ToscaServiceModel toscaServiceModel) {
211     Map<String, NodeTemplate> nodeTemplates = new HashMap<>();
212
213     if (Objects.nonNull(serviceTemplate.getTopology_template())
214         && MapUtils.isNotEmpty(serviceTemplate.getTopology_template().getNode_templates())) {
215       for (Map.Entry<String, NodeTemplate> nodeTemplateEntry : serviceTemplate
216           .getTopology_template().getNode_templates().entrySet()) {
217         if (isTypeOf(nodeTemplateEntry.getValue(), nodeType, serviceTemplate, toscaServiceModel)) {
218           nodeTemplates.put(nodeTemplateEntry.getKey(), nodeTemplateEntry.getValue());
219         }
220
221       }
222     }
223     return nodeTemplates;
224   }
225
226   @Override
227   public Optional<NodeType> fetchNodeType(String nodeTypeKey, Collection<ServiceTemplate>
228       serviceTemplates) {
229     Optional<Map<String, NodeType>> nodeTypeMap = serviceTemplates.stream()
230         .map(st -> st.getNode_types())
231         .filter(nodeTypes -> Objects.nonNull(nodeTypes) && nodeTypes.containsKey(nodeTypeKey))
232         .findFirst();
233     if (nodeTypeMap.isPresent()) {
234       return Optional.ofNullable(nodeTypeMap.get().get(nodeTypeKey));
235     }
236     return Optional.empty();
237   }
238
239   @Override
240   public boolean isTypeOf(NodeTemplate nodeTemplate, String nodeType,
241                           ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
242     if (nodeTemplate == null) {
243       return false;
244     }
245
246     if (isNodeTemplateOfTypeNodeType(nodeTemplate, nodeType)) {
247       return true;
248     }
249
250     Optional<Boolean> nodeTypeExistInServiceTemplateHierarchy =
251         isNodeTypeExistInServiceTemplateHierarchy(nodeType, nodeTemplate.getType(), serviceTemplate,
252             toscaServiceModel, null);
253     return nodeTypeExistInServiceTemplateHierarchy.orElseThrow(() -> new CoreException(
254         new ToscaNodeTypeNotFoundErrorBuilder(nodeTemplate.getType()).build()));
255   }
256
257   @Override
258   public List<RequirementAssignment> getRequirements(NodeTemplate nodeTemplate,
259                                                      String requirementId) {
260     List<RequirementAssignment> requirements = new ArrayList<>();
261     List<Map<String, RequirementAssignment>> requirementList = nodeTemplate.getRequirements();
262     if (requirementList != null) {
263       requirementList.stream().filter(reqMap -> reqMap.get(requirementId) != null)
264           .forEach(reqMap -> {
265             ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
266             RequirementAssignment reqAssignment = toscaExtensionYamlUtil
267                 .yamlToObject(toscaExtensionYamlUtil.objectToYaml(reqMap.get(requirementId)),
268                     RequirementAssignment.class);
269             requirements.add(reqAssignment);
270           });
271     }
272     return requirements;
273   }
274
275   @Override
276   public Optional<NodeTemplate> getNodeTemplateById(ServiceTemplate serviceTemplate,
277                                                     String nodeTemplateId) {
278     if ((serviceTemplate.getTopology_template() != null)
279         && (serviceTemplate.getTopology_template().getNode_templates() != null)
280         && (serviceTemplate.getTopology_template().getNode_templates().get(nodeTemplateId)
281         != null)) {
282       return Optional
283           .of(serviceTemplate.getTopology_template().getNode_templates().get(nodeTemplateId));
284     }
285     return Optional.empty();
286   }
287
288   @Override
289   public Optional<String> getSubstituteServiceTemplateName(String substituteNodeTemplateId,
290                                                            NodeTemplate substitutableNodeTemplate) {
291     if (!isSubstitutableNodeTemplate(substitutableNodeTemplate)) {
292       return Optional.empty();
293     }
294
295     if (substitutableNodeTemplate.getProperties() != null
296         && substitutableNodeTemplate.getProperties()
297         .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME) != null) {
298       Object serviceTemplateFilter = substitutableNodeTemplate.getProperties()
299           .get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
300       if (serviceTemplateFilter != null && serviceTemplateFilter instanceof Map) {
301         Object substituteServiceTemplate = ((Map) serviceTemplateFilter)
302             .get(ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME);
303         handleNoSubstituteServiceTemplate(substituteNodeTemplateId, substituteServiceTemplate);
304         return Optional.of(substituteServiceTemplate.toString());
305       }
306     }
307     MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
308         LoggerTragetServiceName.ADD_ENTITIES_TO_TOSCA, ErrorLevel.ERROR.name(),
309         LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.INVALID_PROPERTY);
310     throw new CoreException(
311         new ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder(substituteNodeTemplateId)
312             .build());
313   }
314
315   private void handleNoSubstituteServiceTemplate(String substituteNodeTemplateId,
316                                                  Object substituteServiceTemplate) {
317     if (substituteServiceTemplate == null) {
318       MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
319           LoggerTragetServiceName.ADD_ENTITIES_TO_TOSCA, ErrorLevel.ERROR.name(),
320           LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.INVALID_PROPERTY);
321       throw new CoreException(
322           new ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder(substituteNodeTemplateId)
323               .build());
324     }
325   }
326
327   @Override
328   public Map<String, NodeTemplate> getSubstitutableNodeTemplates(ServiceTemplate serviceTemplate) {
329     Map<String, NodeTemplate> substitutableNodeTemplates = new HashMap<>();
330
331     if (serviceTemplate == null
332         || serviceTemplate.getTopology_template() == null
333         || serviceTemplate.getTopology_template().getNode_templates() == null) {
334       return substitutableNodeTemplates;
335     }
336
337     Map<String, NodeTemplate> nodeTemplates =
338         serviceTemplate.getTopology_template().getNode_templates();
339     for (Map.Entry<String, NodeTemplate> entry : nodeTemplates.entrySet()) {
340       String nodeTemplateId = entry.getKey();
341       NodeTemplate nodeTemplate = entry.getValue();
342       if (isSubstitutableNodeTemplate(nodeTemplate)) {
343         substitutableNodeTemplates.put(nodeTemplateId, nodeTemplate);
344       }
345     }
346
347     return substitutableNodeTemplates;
348   }
349
350   @Override
351   public Optional<Map.Entry<String, NodeTemplate>> getSubstitutionMappedNodeTemplateByExposedReq(
352       String substituteServiceTemplateFileName, ServiceTemplate substituteServiceTemplate,
353       String requirementId) {
354     if (isSubstitutionServiceTemplate(substituteServiceTemplateFileName,
355         substituteServiceTemplate)) {
356       Map<String, List<String>> substitutionMappingRequirements =
357           substituteServiceTemplate.getTopology_template().getSubstitution_mappings()
358               .getRequirements();
359       if (substitutionMappingRequirements != null) {
360         List<String> requirementMapping = substitutionMappingRequirements.get(requirementId);
361         if (requirementMapping != null && !requirementMapping.isEmpty()) {
362           String mappedNodeTemplateId = requirementMapping.get(0);
363           Optional<NodeTemplate> mappedNodeTemplate =
364               getNodeTemplateById(substituteServiceTemplate, mappedNodeTemplateId);
365           mappedNodeTemplate.orElseThrow(() -> new CoreException(
366               new ToscaInvalidEntryNotFoundErrorBuilder("Node Template", mappedNodeTemplateId)
367                   .build()));
368           Map.Entry<String, NodeTemplate> mappedNodeTemplateEntry =
369               new Map.Entry<String, NodeTemplate>() {
370                 @Override
371                 public String getKey() {
372                   return mappedNodeTemplateId;
373                 }
374
375                 @Override
376                 public NodeTemplate getValue() {
377                   return mappedNodeTemplate.get();
378                 }
379
380                 @Override
381                 public NodeTemplate setValue(NodeTemplate value) {
382                   return null;
383                 }
384               };
385           return Optional.of(mappedNodeTemplateEntry);
386         }
387       }
388     }
389     return Optional.empty();
390   }
391
392   /*
393   match only for the input which is not null
394    */
395   @Override
396   public boolean isDesiredRequirementAssignment(RequirementAssignment requirementAssignment,
397                                                 String capability, String node,
398                                                 String relationship) {
399     if (isSameCapability(requirementAssignment, capability)) {
400       return false;
401     }
402
403     if (isSameRequirement(requirementAssignment, node)) {
404       return false;
405     }
406
407     if (isSameRelationship(requirementAssignment, relationship)) {
408       return false;
409     }
410
411     return !(capability == null && node == null && relationship == null);
412
413   }
414
415   private boolean isSameRelationship(RequirementAssignment requirementAssignment,
416                                      String relationship) {
417     return relationship != null && (requirementAssignment.getRelationship() == null
418         || !requirementAssignment.getRelationship().equals(relationship));
419   }
420
421   private boolean isSameRequirement(RequirementAssignment requirementAssignment, String node) {
422     return node != null && (requirementAssignment.getNode() == null
423         || !requirementAssignment.getNode().equals(node));
424   }
425
426   private boolean isSameCapability(RequirementAssignment requirementAssignment, String capability) {
427     return capability != null && (requirementAssignment.getCapability() == null
428        || !requirementAssignment.getCapability().equals(capability));
429   }
430
431   @Override
432   public Object getFlatEntity(ToscaElementTypes elementType, String typeId,
433                               ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel) {
434     Object returnEntity;
435
436     switch (elementType) {
437       case CAPABILITY_TYPE:
438         returnEntity = new CapabilityType();
439         break;
440       case NODE_TYPE:
441         returnEntity = new NodeType();
442         break;
443       default:
444         MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
445             LoggerTragetServiceName.ADD_ENTITIES_TO_TOSCA, ErrorLevel.ERROR.name(),
446             LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.UNSUPPORTED_ENTITY);
447         throw new RuntimeException(
448             "Entity[" + elementType + "] id[" + typeId + "] flat not supported");
449     }
450
451     scanAnFlatEntity(elementType, typeId, returnEntity, serviceTemplate, toscaModel,
452         new ArrayList<>(), 0);
453
454
455     return returnEntity;
456   }
457
458   @Override
459   public boolean isSubstitutableNodeTemplate(NodeTemplate nodeTemplate) {
460     return nodeTemplate.getDirectives() != null
461         && nodeTemplate.getDirectives().contains(ToscaConstants
462         .NODE_TEMPLATE_DIRECTIVE_SUBSTITUTABLE);
463   }
464
465   private Optional<Boolean> isNodeTypeExistInServiceTemplateHierarchy(
466       String nodeTypeToMatch,
467       String nodeTypeToSearch,
468       ServiceTemplate serviceTemplate,
469       ToscaServiceModel toscaServiceModel,
470       Set<String> analyzedImportFiles) {
471     Map<String, NodeType> searchableNodeTypes = serviceTemplate.getNode_types();
472     if (!MapUtils.isEmpty(searchableNodeTypes)) {
473       NodeType nodeType = searchableNodeTypes.get(nodeTypeToSearch);
474       if (Objects.nonNull(nodeType)) {
475         if (Objects.equals(nodeType.getDerived_from(), nodeTypeToMatch)) {
476           return Optional.of(true);
477         } else if (isNodeTypeIsToscaRoot(nodeType)) {
478           return Optional.of(false);
479         } else {
480           return isNodeTypeExistInServiceTemplateHierarchy(nodeTypeToMatch,
481               nodeType.getDerived_from(), serviceTemplate, toscaServiceModel, null);
482         }
483       } else {
484         return isNodeTypeExistInImports(nodeTypeToMatch, nodeTypeToSearch, serviceTemplate,
485             toscaServiceModel, analyzedImportFiles);
486       }
487     }
488     return isNodeTypeExistInImports(nodeTypeToMatch, nodeTypeToSearch, serviceTemplate,
489         toscaServiceModel, analyzedImportFiles);
490
491   }
492
493   private Optional<Boolean> isNodeTypeExistInImports(String nodeTypeToMatch,
494                                                      String nodeTypeToSearch,
495                                                      ServiceTemplate serviceTemplate,
496                                                      ToscaServiceModel toscaServiceModel,
497                                                      Set<String> filesScanned) {
498     List<Map<String, Import>> imports = serviceTemplate.getImports();
499     if (CollectionUtils.isEmpty(imports)) {
500       return Optional.empty();
501     }
502
503     Set<String> createdFilesScanned = createFilesScannedSet(filesScanned);
504
505     for (Map<String, Import> map : imports) {
506       ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
507       Import anImport = toscaExtensionYamlUtil
508           .yamlToObject(toscaExtensionYamlUtil.objectToYaml(map.values().iterator().next()),
509               Import.class);
510       handleImportWithNoFileEntry(anImport);
511       String importFile = anImport.getFile();
512       ServiceTemplate template =
513           toscaServiceModel.getServiceTemplates().get(fetchFileNameForImport(importFile,
514               serviceTemplate.getMetadata() == null ? null
515                   : serviceTemplate.getMetadata().get("filename")));
516       if (Objects.isNull(template)
517           || createdFilesScanned.contains(ToscaUtil.getServiceTemplateFileName(template))) {
518         continue;
519       } else {
520         createdFilesScanned.add(ToscaUtil.getServiceTemplateFileName(template));
521       }
522       Optional<Boolean> nodeTypeExistInServiceTemplateHierarchy =
523           isNodeTypeExistInServiceTemplateHierarchy(nodeTypeToMatch, nodeTypeToSearch, template,
524               toscaServiceModel, createdFilesScanned);
525       if (nodeTypeExistInServiceTemplateHierarchy.isPresent()
526           && (nodeTypeExistInServiceTemplateHierarchy.get())) {
527         createdFilesScanned.clear();
528         return Optional.of(true);
529       }
530
531     }
532     return Optional.of(false);
533   }
534
535   private void handleImportWithNoFileEntry(Import anImport) {
536     if (Objects.isNull(anImport) || Objects.isNull(anImport.getFile())) {
537       throw new RuntimeException("import without file entry");
538     }
539   }
540
541   private Set<String> createFilesScannedSet(Set<String> filesScanned) {
542     Set<String> retFileScanned = filesScanned;
543     if (Objects.isNull(retFileScanned)) {
544       retFileScanned = new HashSet<>();
545     }
546     return retFileScanned;
547   }
548
549   private boolean isNodeTypeIsToscaRoot(NodeType stNodeType) {
550     return Objects.equals(stNodeType.getDerived_from(), ToscaNodeType.NATIVE_ROOT);
551   }
552
553   private boolean isNodeTemplateOfTypeNodeType(NodeTemplate nodeTemplate, String nodeType) {
554     return Objects.equals(nodeTemplate.getType(), nodeType);
555   }
556
557   private boolean isSubstitutionServiceTemplate(String substituteServiceTemplateFileName,
558                                                 ServiceTemplate substituteServiceTemplate) {
559     if (substituteServiceTemplate != null
560         && substituteServiceTemplate.getTopology_template() != null
561         && substituteServiceTemplate.getTopology_template().getSubstitution_mappings() != null) {
562       if (substituteServiceTemplate.getTopology_template().getSubstitution_mappings()
563           .getNode_type() == null) {
564         throw new CoreException(new ToscaInvalidSubstitutionServiceTemplateErrorBuilder(
565             substituteServiceTemplateFileName).build());
566       }
567       return true;
568     }
569     return false;
570
571   }
572
573   private boolean scanAnFlatEntity(ToscaElementTypes elementType, String typeId, Object entity,
574                                    ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel,
575                                    List<String> filesScanned, int rootScanStartInx) {
576
577
578     boolean entityFound = enrichEntityFromCurrentServiceTemplate(elementType, typeId, entity,
579         serviceTemplate,toscaModel, filesScanned, rootScanStartInx);
580     if (!entityFound) {
581       List<Map<String, Import>> imports = serviceTemplate.getImports();
582       if (CollectionUtils.isEmpty(imports)) {
583         return false;
584       }
585       boolean found = false;
586       for (Map<String, Import> importMap : imports) {
587         if (found) {
588           return true;
589         }
590         found = isFlatEntity(importMap, entity, serviceTemplate, filesScanned,
591             toscaModel,elementType,typeId);
592       }
593       return found;
594     }
595     return true;
596   }
597
598   private boolean isFlatEntity(Map<String, Import> importMap,
599                                Object entity,
600                                ServiceTemplate serviceTemplate,
601                                List<String> filesScanned,
602                                ToscaServiceModel toscaModel,
603                                ToscaElementTypes elementType, String typeId) {
604     boolean found = false;
605     ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
606     for (Object importObject : importMap.values()) {
607       Import importServiceTemplate = toscaExtensionYamlUtil
608           .yamlToObject(toscaExtensionYamlUtil.objectToYaml(importObject), Import.class);
609       String fileName = fetchFileNameForImport(importServiceTemplate.getFile(),
610           serviceTemplate.getMetadata() == null ? null : serviceTemplate.getMetadata().get(
611               "filename"));
612       if (filesScanned.contains(fileName)) {
613         return false;
614       } else {
615         filesScanned.add(fileName);
616       }
617       ServiceTemplate template = toscaModel.getServiceTemplates().get(fileName);
618       found = scanAnFlatEntity(elementType, typeId, entity, template, toscaModel,
619           filesScanned, filesScanned.size());
620     }
621     return found;
622   }
623
624   private String fetchFileNameForImport(String importServiceTemplateFile,
625                                         String currentMetadatafileName) {
626     if (importServiceTemplateFile.contains("../")) {
627       return importServiceTemplateFile.replace("../", "");
628     } else if (currentMetadatafileName != null) {
629       return currentMetadatafileName.substring(0, currentMetadatafileName.indexOf('/')) + "/"
630           + importServiceTemplateFile;
631     } else {
632       return importServiceTemplateFile;
633     }
634
635   }
636
637   private boolean enrichEntityFromCurrentServiceTemplate(ToscaElementTypes elementType,
638                                                          String typeId, Object entity,
639                                                          ServiceTemplate serviceTemplate,
640                                                          ToscaServiceModel toscaModel,
641                                                          List<String> filesScanned,
642                                                          int rootScanStartInx) {
643     switch (elementType) {
644       case CAPABILITY_TYPE:
645         if (enrichCapabilityType(elementType, typeId, entity, serviceTemplate, toscaModel,
646             filesScanned, rootScanStartInx)) {
647           return false;
648         }
649         break;
650       case NODE_TYPE:
651         if (enrichNodeTypeInfo(elementType, typeId, entity, serviceTemplate, toscaModel,
652             filesScanned, rootScanStartInx)) {
653           return false;
654         }
655         break;
656       default:
657         MdcDataErrorMessage.createErrorMessageAndUpdateMdc(LoggerConstants.TARGET_ENTITY_DB,
658             LoggerTragetServiceName.ADD_ENTITIES_TO_TOSCA, ErrorLevel.ERROR.name(),
659             LoggerErrorCode.DATA_ERROR.getErrorCode(), LoggerErrorDescription.UNSUPPORTED_ENTITY);
660         throw new RuntimeException(
661             "Entity[" + elementType + "] id[" + typeId + "] flat not supported");
662     }
663
664     return true;
665
666
667   }
668
669   private boolean enrichNodeTypeInfo(ToscaElementTypes elementType, String typeId, Object entity,
670                                      ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel,
671                                      List<String> filesScanned, int rootScanStartInx) {
672     String derivedFrom;
673     if (serviceTemplate.getNode_types() != null
674         && serviceTemplate.getNode_types().containsKey(typeId)) {
675
676       filesScanned.clear();
677       NodeType targetNodeType = (NodeType) entity;
678       NodeType sourceNodeType = serviceTemplate.getNode_types().get(typeId);
679       derivedFrom = sourceNodeType.getDerived_from();
680       if (derivedFrom != null) {
681         scanAnFlatEntity(elementType, derivedFrom, entity, serviceTemplate, toscaModel,
682             filesScanned, rootScanStartInx);
683       }
684       combineNodeTypeInfo(sourceNodeType, targetNodeType);
685     } else {
686       return true;
687     }
688     return false;
689   }
690
691   private boolean enrichCapabilityType(ToscaElementTypes elementType, String typeId, Object entity,
692                                        ServiceTemplate serviceTemplate,
693                                        ToscaServiceModel toscaModel, List<String> filesScanned,
694                                        int rootScanStartInx) {
695     String derivedFrom;
696     if (serviceTemplate.getCapability_types() != null
697         && serviceTemplate.getCapability_types().containsKey(typeId)) {
698
699       filesScanned.clear();
700       CapabilityType targetCapabilityType = (CapabilityType) entity;
701       CapabilityType sourceCapabilityType = serviceTemplate.getCapability_types().get(typeId);
702       derivedFrom = sourceCapabilityType.getDerived_from();
703       if (derivedFrom != null) {
704         scanAnFlatEntity(elementType, derivedFrom, entity, serviceTemplate, toscaModel,
705             filesScanned, rootScanStartInx);
706       }
707       combineCapabilityTypeInfo(sourceCapabilityType, targetCapabilityType);
708     } else {
709       return true;
710     }
711     return false;
712   }
713
714   private void combineNodeTypeInfo(NodeType sourceNodeType, NodeType targetNodeType) {
715     targetNodeType.setDerived_from(sourceNodeType.getDerived_from());
716     targetNodeType.setDescription(sourceNodeType.getDescription());
717     targetNodeType.setVersion(sourceNodeType.getVersion());
718     targetNodeType.setProperties(
719         CommonMethods.mergeMaps(targetNodeType.getProperties(), sourceNodeType.getProperties()));
720     targetNodeType.setInterfaces(
721         CommonMethods.mergeMaps(targetNodeType.getInterfaces(), sourceNodeType.getInterfaces()));
722     targetNodeType.setArtifacts(
723         CommonMethods.mergeMaps(targetNodeType.getArtifacts(), sourceNodeType.getArtifacts()));
724     targetNodeType.setAttributes(
725         CommonMethods.mergeMaps(targetNodeType.getAttributes(), sourceNodeType.getAttributes()));
726     targetNodeType.setCapabilities(CommonMethods
727         .mergeMaps(targetNodeType.getCapabilities(), sourceNodeType.getCapabilities()));
728     targetNodeType.setRequirements(CommonMethods
729         .mergeListsOfMap(targetNodeType.getRequirements(), sourceNodeType.getRequirements()));
730
731   }
732
733
734   private void combineCapabilityTypeInfo(CapabilityType sourceCapabilityType,
735                                          CapabilityType targetCapabilityType) {
736
737     targetCapabilityType.setAttributes(CommonMethods
738         .mergeMaps(targetCapabilityType.getAttributes(), sourceCapabilityType.getAttributes()));
739     targetCapabilityType.setProperties(CommonMethods
740         .mergeMaps(targetCapabilityType.getProperties(), sourceCapabilityType.getProperties()));
741     targetCapabilityType.setValid_source_types(CommonMethods
742         .mergeLists(targetCapabilityType.getValid_source_types(),
743             sourceCapabilityType.getValid_source_types()));
744
745     if (StringUtils.isNotEmpty(sourceCapabilityType.getDerived_from())) {
746       targetCapabilityType.setDerived_from(sourceCapabilityType.getDerived_from());
747     }
748     if (StringUtils.isNotEmpty(sourceCapabilityType.getDescription())) {
749       targetCapabilityType.setDescription(sourceCapabilityType.getDescription());
750     }
751     if (StringUtils.isNotEmpty(sourceCapabilityType.getVersion())) {
752       targetCapabilityType.setVersion(sourceCapabilityType.getVersion());
753     }
754
755
756   }
757
758
759   /*
760  * Create node type according to the input substitution service template, while the substitution
761  * service template can be mappted to this node type, for substitution mapping.
762  *
763  * @param substitutionServiceTemplate  substitution serivce template
764  * @param nodeTypeDerivedFromValue derived from value for the created node type
765  * @return the node type
766  */
767   @Override
768   public NodeType createInitSubstitutionNodeType(ServiceTemplate substitutionServiceTemplate,
769                                                  String nodeTypeDerivedFromValue) {
770     NodeType substitutionNodeType = new NodeType();
771     substitutionNodeType.setDerived_from(nodeTypeDerivedFromValue);
772     substitutionNodeType.setDescription(substitutionServiceTemplate.getDescription());
773     substitutionNodeType
774         .setProperties(manageSubstitutionNodeTypeProperties(substitutionServiceTemplate));
775     substitutionNodeType
776         .setAttributes(manageSubstitutionNodeTypeAttributes(substitutionServiceTemplate));
777     return substitutionNodeType;
778   }
779
780   @Override
781   public Map<String, PropertyDefinition> manageSubstitutionNodeTypeProperties(
782       ServiceTemplate substitutionServiceTemplate) {
783     Map<String, PropertyDefinition> substitutionNodeTypeProperties = new HashMap<>();
784     Map<String, ParameterDefinition> properties =
785         substitutionServiceTemplate.getTopology_template().getInputs();
786     if (properties == null) {
787       return null;
788     }
789
790     PropertyDefinition propertyDefinition;
791     String toscaPropertyName;
792     for (Map.Entry<String, ParameterDefinition> entry : properties.entrySet()) {
793       toscaPropertyName = entry.getKey();
794       propertyDefinition = new PropertyDefinition();
795       ParameterDefinition parameterDefinition =
796           substitutionServiceTemplate.getTopology_template().getInputs().get(toscaPropertyName);
797       propertyDefinition.setType(parameterDefinition.getType());
798       propertyDefinition.setDescription(parameterDefinition.getDescription());
799       propertyDefinition.set_default(parameterDefinition.get_default());
800       if (parameterDefinition.getRequired() != null) {
801         propertyDefinition.setRequired(parameterDefinition.getRequired());
802       }
803       if (propertyDefinition.get_default() != null) {
804         propertyDefinition.setRequired(false);
805       }
806       if (!CollectionUtils.isEmpty(parameterDefinition.getConstraints())) {
807         propertyDefinition.setConstraints(parameterDefinition.getConstraints());
808       }
809       propertyDefinition.setEntry_schema(parameterDefinition.getEntry_schema());
810       if (parameterDefinition.getStatus() != null) {
811         propertyDefinition.setStatus(parameterDefinition.getStatus());
812       }
813       substitutionNodeTypeProperties.put(toscaPropertyName, propertyDefinition);
814     }
815     return substitutionNodeTypeProperties;
816   }
817
818
819   private Map<String, AttributeDefinition> manageSubstitutionNodeTypeAttributes(
820       ServiceTemplate substitutionServiceTemplate) {
821     Map<String, AttributeDefinition> substitutionNodeTypeAttributes = new HashMap<>();
822     Map<String, ParameterDefinition> attributes =
823         substitutionServiceTemplate.getTopology_template().getOutputs();
824     if (attributes == null) {
825       return null;
826     }
827     AttributeDefinition attributeDefinition;
828     String toscaAttributeName;
829
830     for (Map.Entry<String, ParameterDefinition> entry : attributes.entrySet()) {
831       attributeDefinition = new AttributeDefinition();
832       toscaAttributeName = entry.getKey();
833       ParameterDefinition parameterDefinition =
834           substitutionServiceTemplate.getTopology_template().getOutputs().get(toscaAttributeName);
835       if (parameterDefinition.getType() != null && !parameterDefinition.getType().isEmpty()) {
836         attributeDefinition.setType(parameterDefinition.getType());
837       } else {
838         attributeDefinition.setType(PropertyType.STRING.getDisplayName());
839       }
840       attributeDefinition.setDescription(parameterDefinition.getDescription());
841       attributeDefinition.set_default(parameterDefinition.get_default());
842       attributeDefinition.setEntry_schema(parameterDefinition.getEntry_schema());
843       if (Objects.nonNull(parameterDefinition.getStatus())) {
844         attributeDefinition.setStatus(parameterDefinition.getStatus());
845       }
846       substitutionNodeTypeAttributes.put(toscaAttributeName, attributeDefinition);
847     }
848     return substitutionNodeTypeAttributes;
849   }
850
851   /**
852    * Checks if the requirement exists in the node template.
853    *
854    * @param nodeTemplate          the node template
855    * @param requirementId         the requirement id
856    * @param requirementAssignment the requirement assignment
857    * @return true if the requirement already exists and false otherwise
858    */
859   @Override
860   public boolean isRequirementExistInNodeTemplate(NodeTemplate nodeTemplate,
861                                                   String requirementId,
862                                                   RequirementAssignment requirementAssignment) {
863     List<Map<String, RequirementAssignment>> nodeTemplateRequirements = nodeTemplate
864         .getRequirements();
865     if (nodeTemplateRequirements != null) {
866       return nodeTemplateRequirements.stream()
867           .anyMatch(requirement -> requirement.containsKey(requirementId)
868               && DataModelUtil.compareRequirementAssignment(requirementAssignment,
869               requirement.get(requirementId)));
870     }
871     return false;
872   }
873 }