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