1bc547aed799cfd93cc422956721233545323f73
[sdc.git] /
1 /*
2  * Copyright © 2016-2018 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 java.io.ByteArrayInputStream;
20 import java.io.IOException;
21 import java.lang.reflect.InvocationTargetException;
22 import java.nio.file.Path;
23 import java.nio.file.Paths;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Objects;
32 import java.util.Optional;
33 import java.util.Set;
34 import java.util.zip.ZipEntry;
35 import java.util.zip.ZipInputStream;
36 import org.apache.commons.collections4.CollectionUtils;
37 import org.apache.commons.collections4.MapUtils;
38 import org.apache.commons.lang3.StringUtils;
39 import org.onap.sdc.tosca.datatypes.model.AttributeDefinition;
40 import org.onap.sdc.tosca.datatypes.model.CapabilityDefinition;
41 import org.onap.sdc.tosca.datatypes.model.CapabilityType;
42 import org.onap.sdc.tosca.datatypes.model.DataType;
43 import org.onap.sdc.tosca.datatypes.model.DefinitionOfDataType;
44 import org.onap.sdc.tosca.datatypes.model.Import;
45 import org.onap.sdc.tosca.datatypes.model.InterfaceDefinitionType;
46 import org.onap.sdc.tosca.datatypes.model.NodeTemplate;
47 import org.onap.sdc.tosca.datatypes.model.NodeType;
48 import org.onap.sdc.tosca.datatypes.model.ParameterDefinition;
49 import org.onap.sdc.tosca.datatypes.model.PropertyDefinition;
50 import org.onap.sdc.tosca.datatypes.model.PropertyType;
51 import org.onap.sdc.tosca.datatypes.model.RequirementAssignment;
52 import org.onap.sdc.tosca.datatypes.model.RequirementDefinition;
53 import org.onap.sdc.tosca.datatypes.model.ServiceTemplate;
54 import org.onap.sdc.tosca.services.ToscaExtensionYamlUtil;
55 import org.onap.sdc.tosca.services.YamlUtil;
56 import org.openecomp.core.utilities.CommonMethods;
57 import org.openecomp.core.utilities.file.FileContentHandler;
58 import org.openecomp.core.utilities.file.FileUtils;
59 import org.openecomp.sdc.common.errors.CoreException;
60 import org.openecomp.sdc.common.errors.SdcRuntimeException;
61 import org.openecomp.sdc.common.zip.ZipUtils;
62 import org.openecomp.sdc.common.zip.exception.ZipSlipException;
63 import org.openecomp.sdc.tosca.datatypes.ToscaElementTypes;
64 import org.openecomp.sdc.tosca.datatypes.ToscaFlatData;
65 import org.openecomp.sdc.tosca.datatypes.ToscaServiceModel;
66 import org.openecomp.sdc.tosca.errors.InvalidToscaFile;
67 import org.openecomp.sdc.tosca.errors.InvalidToscaMetaFile;
68 import org.openecomp.sdc.tosca.errors.ToscaElementTypeNotFoundErrorBuilder;
69 import org.openecomp.sdc.tosca.errors.ToscaEntryDefinitionWasNotFound;
70 import org.openecomp.sdc.tosca.errors.ToscaFileNotFoundErrorBuilder;
71 import org.openecomp.sdc.tosca.errors.ToscaInvalidEntryNotFoundErrorBuilder;
72 import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder;
73 import org.openecomp.sdc.tosca.errors.ToscaInvalidSubstitutionServiceTemplateErrorBuilder;
74 import org.openecomp.sdc.tosca.services.DataModelUtil;
75 import org.openecomp.sdc.tosca.services.ToscaAnalyzerService;
76 import org.openecomp.sdc.tosca.services.ToscaConstants;
77 import org.openecomp.sdc.tosca.services.ToscaUtil;
78
79 public class ToscaAnalyzerServiceImpl implements ToscaAnalyzerService {
80
81     private static final String GET_NODE_TYPE_METHOD_NAME = "getNode_types";
82     private static final String GET_DERIVED_FROM_METHOD_NAME = "getDerived_from";
83     private static final String GET_TYPE_METHOD_NAME = "getType";
84     private static final String GET_DATA_TYPE_METHOD_NAME = "getData_types";
85     private static final String GET_INTERFACE_TYPE_METHOD_NAME = "getNormalizeInterfaceTypes";
86     private static final String GET_CAPABILITY_TYPE_METHOD_NAME = "getCapability_types";
87     private static final String TOSCA_DOT = "tosca.";
88     private static final String DOT_ROOT = ".Root";
89     private static final String IMPORTS = "imports";
90     private static final String TOSCA_META_FILE = "TOSCA-Metadata/TOSCA.meta";
91     private static final String ENTRY_DEFINITIONS = "Entry-Definitions";
92
93     @Override
94     public List<Map<String, RequirementDefinition>> calculateExposedRequirements(
95             List<Map<String, RequirementDefinition>> nodeTypeRequirementsDefinitionList,
96             Map<String, RequirementAssignment> nodeTemplateRequirementsAssignment) {
97
98         if (nodeTypeRequirementsDefinitionList == null) {
99             return Collections.emptyList();
100         }
101         for (Map.Entry<String, RequirementAssignment> entry : nodeTemplateRequirementsAssignment.entrySet()) {
102             if (entry.getValue().getNode() != null) {
103                 Optional<RequirementDefinition> requirementDefinition =
104                         DataModelUtil.getRequirementDefinition(nodeTypeRequirementsDefinitionList, entry.getKey());
105                 RequirementDefinition cloneRequirementDefinition;
106                 if (requirementDefinition.isPresent()) {
107                     cloneRequirementDefinition = requirementDefinition.get().clone();
108                     updateRequirementDefinition(nodeTypeRequirementsDefinitionList, entry, cloneRequirementDefinition);
109                 }
110             } else {
111                 for (Map<String, RequirementDefinition> nodeTypeRequirementsMap : nodeTypeRequirementsDefinitionList) {
112                     updateMinMaxOccurencesForNodeTypeRequirement(entry, nodeTypeRequirementsMap);
113                 }
114             }
115         }
116         return nodeTypeRequirementsDefinitionList;
117     }
118
119     @Override
120     public ToscaServiceModel loadToscaCsarPackage(byte[] toscaCsarPackage) {
121         ToscaServiceModel toscaServiceModel = new ToscaServiceModel();
122         ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
123         FileContentHandler artifactFiles = new FileContentHandler();
124
125         try (ZipInputStream inputZipStream = new ZipInputStream(new ByteArrayInputStream(toscaCsarPackage))) {
126             ZipEntry zipEntry;
127             while ((zipEntry = inputZipStream.getNextEntry()) != null) {
128                 ZipUtils.checkForZipSlipInRead(zipEntry);
129                 byte[] fileContent = FileUtils.toByteArray(inputZipStream);
130                 String currentEntryName = zipEntry.getName();
131                 if (!isFile(currentEntryName)) {
132                     continue;
133                 }
134                 if (isYamlFile(currentEntryName) && isToscaYamlFile(fileContent)) {
135                     loadToscaYamlFile(toscaServiceModel, toscaExtensionYamlUtil, fileContent, currentEntryName);
136                 } else if (currentEntryName.equals(TOSCA_META_FILE)) {
137                     loadToscaMetaFile(toscaServiceModel, fileContent);
138                 } else {
139                     artifactFiles.addFile(currentEntryName, fileContent);
140                 }
141             }
142             toscaServiceModel.setArtifactFiles(artifactFiles);
143             if (StringUtils.isEmpty(toscaServiceModel.getEntryDefinitionServiceTemplate())) {
144                 handleToscaCsarWithoutToscaMetadata(toscaServiceModel);
145             }
146
147         } catch (IOException | ZipSlipException exc) {
148             throw new SdcRuntimeException(exc.getMessage(), exc);
149         }
150         return toscaServiceModel;
151     }
152
153     private void handleToscaCsarWithoutToscaMetadata(ToscaServiceModel toscaServiceModel) {
154         for (String fileName : toscaServiceModel.getServiceTemplates().keySet()) {
155             if (!fileName.contains("/")) {
156                 if (StringUtils.isNotEmpty(toscaServiceModel.getEntryDefinitionServiceTemplate())) {
157                     throw new CoreException(new ToscaEntryDefinitionWasNotFound().build());
158                 }
159                 toscaServiceModel.setEntryDefinitionServiceTemplate(fileName);
160             }
161         }
162     }
163
164     void loadToscaMetaFile(ToscaServiceModel toscaServiceModel, byte[] toscaMetaFileContent) {
165         String toscaMeta = new String(toscaMetaFileContent);
166         Map toscaMetaMap = new YamlUtil().yamlToObject(toscaMeta, Map.class);
167         if (Objects.isNull(toscaMetaMap.get(ENTRY_DEFINITIONS))) {
168             throw new CoreException(new InvalidToscaMetaFile(ENTRY_DEFINITIONS).build());
169         }
170         String entryDefinition = (String) toscaMetaMap.get(ENTRY_DEFINITIONS);
171         toscaServiceModel.setEntryDefinitionServiceTemplate(entryDefinition);
172     }
173
174     void loadToscaYamlFile(ToscaServiceModel toscaServiceModel, ToscaExtensionYamlUtil toscaExtensionYamlUtil,
175                            byte[] fileContent, String fileFullName) {
176         try {
177             ServiceTemplate serviceTemplate =
178                     toscaExtensionYamlUtil.yamlToObject(new String(fileContent), ServiceTemplate.class);
179             toscaServiceModel.addServiceTemplate(fileFullName, serviceTemplate);
180
181         } catch (Exception exc) {
182             throw new CoreException(new InvalidToscaFile(fileFullName, exc.getMessage()).build());
183         }
184     }
185
186     private static boolean isFile(String currentEntryName) {
187         return !(currentEntryName.endsWith("\\") || currentEntryName.endsWith("/"));
188     }
189
190     private boolean isYamlFile(String fileName) {
191         return fileName.endsWith("yaml") || fileName.endsWith("yml");
192     }
193
194     private boolean isToscaYamlFile(byte[] fileContent) {
195         Map fileMap = new YamlUtil().yamlToObject(new String(fileContent), Map.class);
196         return fileMap.containsKey("tosca_definitions_version");
197     }
198
199     private void updateMinMaxOccurencesForNodeTypeRequirement(Map.Entry<String, RequirementAssignment> entry,
200             Map<String, RequirementDefinition> nodeTypeRequirementsMap) {
201         Object max = nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences() != null
202                              && nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences().length > 0
203                              ? nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences()[1] : 1;
204         Object min = nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences() != null
205                              && nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences().length > 0
206                              ? nodeTypeRequirementsMap.get(entry.getKey()).getOccurrences()[0] : 1;
207         nodeTypeRequirementsMap.get(entry.getKey()).setOccurrences(new Object[] {min, max});
208     }
209
210     private void updateRequirementDefinition(
211             List<Map<String, RequirementDefinition>> nodeTypeRequirementsDefinitionList,
212             Map.Entry<String, RequirementAssignment> entry, RequirementDefinition cloneRequirementDefinition) {
213         if (!evaluateRequirementFulfillment(cloneRequirementDefinition)) {
214             CommonMethods
215                     .mergeEntryInList(entry.getKey(), cloneRequirementDefinition, nodeTypeRequirementsDefinitionList);
216         } else {
217             DataModelUtil.removeRequirementsDefinition(nodeTypeRequirementsDefinitionList, entry.getKey());
218         }
219     }
220
221     private static boolean evaluateRequirementFulfillment(RequirementDefinition requirementDefinition) {
222         Object[] occurrences = requirementDefinition.getOccurrences();
223         if (occurrences == null) {
224             requirementDefinition.setOccurrences(new Object[] {1, 1});
225             return false;
226         }
227         if (occurrences[1].equals(ToscaConstants.UNBOUNDED)) {
228             return false;
229         }
230
231         if (occurrences[1].equals(1)) {
232             return true;
233         }
234         occurrences[1] = (Integer) occurrences[1] - 1;
235         return false;
236     }
237
238     @Override
239     public Map<String, CapabilityDefinition> calculateExposedCapabilities(
240             Map<String, CapabilityDefinition> nodeTypeCapabilitiesDefinition,
241             Map<String, Map<String, RequirementAssignment>> fullFilledRequirementsDefinitionMap) {
242
243         String capabilityKey;
244         String capability;
245         String node;
246         for (Map.Entry<String, Map<String, RequirementAssignment>> entry : fullFilledRequirementsDefinitionMap
247                                                                                    .entrySet()) {
248             for (Map.Entry<String, RequirementAssignment> fullFilledEntry : entry.getValue().entrySet()) {
249
250
251                 capability = fullFilledEntry.getValue().getCapability();
252                 node = fullFilledEntry.getValue().getNode();
253                 capabilityKey = capability + "_" + node;
254                 CapabilityDefinition capabilityDefinition = nodeTypeCapabilitiesDefinition.get(capabilityKey);
255                 if (capabilityDefinition != null) {
256                     CapabilityDefinition clonedCapabilityDefinition = capabilityDefinition.clone();
257                     nodeTypeCapabilitiesDefinition.put(capabilityKey, capabilityDefinition.clone());
258                     updateNodeTypeCapabilitiesDefinition(nodeTypeCapabilitiesDefinition, capabilityKey,
259                             clonedCapabilityDefinition);
260                 }
261             }
262         }
263
264         Map<String, CapabilityDefinition> exposedCapabilitiesDefinition = new HashMap<>();
265         for (Map.Entry<String, CapabilityDefinition> entry : nodeTypeCapabilitiesDefinition.entrySet()) {
266             exposedCapabilitiesDefinition.put(entry.getKey(), entry.getValue());
267         }
268         return exposedCapabilitiesDefinition;
269     }
270
271     private void updateNodeTypeCapabilitiesDefinition(Map<String, CapabilityDefinition> nodeTypeCapabilitiesDefinition,
272             String capabilityKey, CapabilityDefinition clonedCapabilityDefinition) {
273         if (evaluateCapabilityFulfillment(clonedCapabilityDefinition)) {
274             nodeTypeCapabilitiesDefinition.remove(capabilityKey);
275         } else {
276             nodeTypeCapabilitiesDefinition.put(capabilityKey, clonedCapabilityDefinition);
277         }
278     }
279
280     private static boolean evaluateCapabilityFulfillment(CapabilityDefinition capabilityDefinition) {
281
282         Object[] occurrences = capabilityDefinition.getOccurrences();
283         if (occurrences == null) {
284             capabilityDefinition.setOccurrences(new Object[] {1, ToscaConstants.UNBOUNDED});
285             return false;
286         }
287         if (occurrences[1].equals(ToscaConstants.UNBOUNDED)) {
288             return false;
289         }
290
291         if (occurrences[1].equals(1)) {
292             return true;
293         }
294         occurrences[1] = (Integer) occurrences[1] - 1;
295         return false;
296     }
297
298     /*
299       node template with type equal to node type or derived from node type
300        */
301     @Override
302     public Map<String, NodeTemplate> getNodeTemplatesByType(ServiceTemplate serviceTemplate, String nodeType,
303             ToscaServiceModel toscaServiceModel) {
304         Map<String, NodeTemplate> nodeTemplates = new HashMap<>();
305
306         if (Objects.nonNull(serviceTemplate.getTopology_template()) && MapUtils.isNotEmpty(
307                 serviceTemplate.getTopology_template().getNode_templates())) {
308             for (Map.Entry<String, NodeTemplate> nodeTemplateEntry : serviceTemplate.getTopology_template()
309                                                                                     .getNode_templates().entrySet()) {
310                 if (isTypeOf(nodeTemplateEntry.getValue(), nodeType, serviceTemplate, toscaServiceModel)) {
311                     nodeTemplates.put(nodeTemplateEntry.getKey(), nodeTemplateEntry.getValue());
312                 }
313
314             }
315         }
316         return nodeTemplates;
317     }
318
319     @Override
320     public Optional<NodeType> fetchNodeType(String nodeTypeKey, Collection<ServiceTemplate> serviceTemplates) {
321         Optional<Map<String, NodeType>> nodeTypeMap = serviceTemplates.stream().map(ServiceTemplate::getNode_types)
322                                                                       .filter(nodeTypes -> Objects.nonNull(nodeTypes)
323                                                                                                    && nodeTypes
324                                                                                                               .containsKey(
325                                                                                                                       nodeTypeKey))
326                                                                       .findFirst();
327         return nodeTypeMap.map(stringNodeTypeMap -> stringNodeTypeMap.get(nodeTypeKey));
328     }
329
330     @Override
331     public boolean isTypeOf(NodeTemplate nodeTemplate, String nodeType, ServiceTemplate serviceTemplate,
332             ToscaServiceModel toscaServiceModel) {
333         return isTypeOf(nodeTemplate, nodeType, GET_NODE_TYPE_METHOD_NAME, serviceTemplate, toscaServiceModel);
334     }
335
336     @Override
337     public boolean isTypeOf(InterfaceDefinitionType interfaceDefinition, String interfaceType,
338             ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
339         return isTypeOf(interfaceDefinition, interfaceType, GET_INTERFACE_TYPE_METHOD_NAME, serviceTemplate,
340                 toscaServiceModel);
341     }
342
343     @Override
344     public boolean isTypeOf(DefinitionOfDataType parameterDefinition, String dataType, ServiceTemplate serviceTemplate,
345             ToscaServiceModel toscaServiceModel) {
346         return isTypeOf(parameterDefinition, dataType, GET_DATA_TYPE_METHOD_NAME, serviceTemplate, toscaServiceModel);
347     }
348
349     @Override
350     public boolean isTypeOf(CapabilityDefinition capabilityDefinition, String capabilityType,
351             ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
352         return isTypeOf(capabilityDefinition, capabilityType, GET_CAPABILITY_TYPE_METHOD_NAME, serviceTemplate,
353                 toscaServiceModel);
354     }
355
356     @Override
357     public List<RequirementAssignment> getRequirements(NodeTemplate nodeTemplate, String requirementId) {
358         List<RequirementAssignment> requirements = new ArrayList<>();
359         List<Map<String, RequirementAssignment>> requirementList = nodeTemplate.getRequirements();
360         if (requirementList != null) {
361             requirementList.stream().filter(reqMap -> reqMap.get(requirementId) != null).forEach(reqMap -> {
362                 ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
363                 RequirementAssignment reqAssignment = toscaExtensionYamlUtil.yamlToObject(
364                         toscaExtensionYamlUtil.objectToYaml(reqMap.get(requirementId)), RequirementAssignment.class);
365                 requirements.add(reqAssignment);
366             });
367         }
368         return requirements;
369     }
370
371     @Override
372     public Optional<NodeTemplate> getNodeTemplateById(ServiceTemplate serviceTemplate, String nodeTemplateId) {
373         if ((serviceTemplate.getTopology_template() != null) && (
374                 serviceTemplate.getTopology_template().getNode_templates() != null) && (
375                 serviceTemplate.getTopology_template().getNode_templates().get(nodeTemplateId) != null)) {
376             return Optional.of(serviceTemplate.getTopology_template().getNode_templates().get(nodeTemplateId));
377         }
378         return Optional.empty();
379     }
380
381     @Override
382     public Optional<String> getSubstituteServiceTemplateName(String substituteNodeTemplateId,
383             NodeTemplate substitutableNodeTemplate) {
384         if (!isSubstitutableNodeTemplate(substitutableNodeTemplate)) {
385             return Optional.empty();
386         }
387
388         if (substitutableNodeTemplate.getProperties() != null &&
389                     substitutableNodeTemplate.getProperties().get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME)
390                             != null) {
391             Object serviceTemplateFilter =
392                     substitutableNodeTemplate.getProperties().get(ToscaConstants.SERVICE_TEMPLATE_FILTER_PROPERTY_NAME);
393             if (serviceTemplateFilter instanceof Map) {
394                 Object substituteServiceTemplate =
395                         ((Map) serviceTemplateFilter).get(ToscaConstants.SUBSTITUTE_SERVICE_TEMPLATE_PROPERTY_NAME);
396                 handleNoSubstituteServiceTemplate(substituteNodeTemplateId, substituteServiceTemplate);
397                 return Optional.of(substituteServiceTemplate.toString());
398             }
399         }
400         throw new CoreException(
401                 new ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder(substituteNodeTemplateId).build());
402     }
403
404     private void handleNoSubstituteServiceTemplate(String substituteNodeTemplateId, Object substituteServiceTemplate) {
405         if (substituteServiceTemplate == null) {
406             throw new CoreException(
407                     new ToscaInvalidSubstituteNodeTemplatePropertiesErrorBuilder(substituteNodeTemplateId).build());
408         }
409     }
410
411     @Override
412     public Map<String, NodeTemplate> getSubstitutableNodeTemplates(ServiceTemplate serviceTemplate) {
413         Map<String, NodeTemplate> substitutableNodeTemplates = new HashMap<>();
414
415         if (serviceTemplate == null || serviceTemplate.getTopology_template() == null
416                     || serviceTemplate.getTopology_template().getNode_templates() == null) {
417             return substitutableNodeTemplates;
418         }
419
420         Map<String, NodeTemplate> nodeTemplates = serviceTemplate.getTopology_template().getNode_templates();
421         for (Map.Entry<String, NodeTemplate> entry : nodeTemplates.entrySet()) {
422             String nodeTemplateId = entry.getKey();
423             NodeTemplate nodeTemplate = entry.getValue();
424             if (isSubstitutableNodeTemplate(nodeTemplate)) {
425                 substitutableNodeTemplates.put(nodeTemplateId, nodeTemplate);
426             }
427         }
428
429         return substitutableNodeTemplates;
430     }
431
432     @Override
433     public Optional<Map.Entry<String, NodeTemplate>> getSubstitutionMappedNodeTemplateByExposedReq(
434             String substituteServiceTemplateFileName, ServiceTemplate substituteServiceTemplate, String requirementId) {
435         if (isSubstitutionServiceTemplate(substituteServiceTemplateFileName, substituteServiceTemplate)) {
436             Map<String, List<String>> substitutionMappingRequirements =
437                     substituteServiceTemplate.getTopology_template().getSubstitution_mappings().getRequirements();
438             if (substitutionMappingRequirements != null) {
439                 List<String> requirementMapping = substitutionMappingRequirements.get(requirementId);
440                 if (requirementMapping != null && !requirementMapping.isEmpty()) {
441                     String mappedNodeTemplateId = requirementMapping.get(0);
442                     Optional<NodeTemplate> mappedNodeTemplate =
443                             getNodeTemplateById(substituteServiceTemplate, mappedNodeTemplateId);
444                     mappedNodeTemplate.orElseThrow(() -> new CoreException(
445                             new ToscaInvalidEntryNotFoundErrorBuilder("Node Template", mappedNodeTemplateId).build()));
446                     Map.Entry<String, NodeTemplate> mappedNodeTemplateEntry = new Map.Entry<String, NodeTemplate>() {
447                         @Override
448                         public String getKey() {
449                             return mappedNodeTemplateId;
450                         }
451
452                         @Override
453                         public NodeTemplate getValue() {
454                             return mappedNodeTemplate.get();
455                         }
456
457                         @Override
458                         public NodeTemplate setValue(NodeTemplate value) {
459                             return null;
460                         }
461                     };
462                     return Optional.of(mappedNodeTemplateEntry);
463                 }
464             }
465         }
466         return Optional.empty();
467     }
468
469     /*
470     match only for the input which is not null
471      */
472     @Override
473     public boolean isDesiredRequirementAssignment(RequirementAssignment requirementAssignment, String capability,
474             String node, String relationship) {
475         if (isSameCapability(requirementAssignment, capability)) {
476             return false;
477         }
478
479         if (isSameRequirement(requirementAssignment, node)) {
480             return false;
481         }
482
483         if (isSameRelationship(requirementAssignment, relationship)) {
484             return false;
485         }
486
487         return !(capability == null && node == null && relationship == null);
488
489     }
490
491     private boolean isSameRelationship(RequirementAssignment requirementAssignment, String relationship) {
492         return relationship != null && (requirementAssignment.getRelationship() == null || !requirementAssignment
493                                                                                                     .getRelationship()
494                                                                                                     .equals(relationship));
495     }
496
497     private boolean isSameRequirement(RequirementAssignment requirementAssignment, String node) {
498         return node != null && (requirementAssignment.getNode() == null || !requirementAssignment.getNode()
499                                                                                                  .equals(node));
500     }
501
502     private boolean isSameCapability(RequirementAssignment requirementAssignment, String capability) {
503         return capability != null && (requirementAssignment.getCapability() == null || !requirementAssignment
504                                                                                                 .getCapability()
505                                                                                                 .equals(capability));
506     }
507
508     @Override
509     public ToscaFlatData getFlatEntity(ToscaElementTypes elementType, String typeId, ServiceTemplate serviceTemplate,
510             ToscaServiceModel toscaModel) {
511         ToscaFlatData flatData = new ToscaFlatData();
512         flatData.setElementType(elementType);
513
514         switch (elementType) {
515             case CAPABILITY_TYPE:
516                 flatData.setFlatEntity(new CapabilityType());
517                 break;
518             case NODE_TYPE:
519                 flatData.setFlatEntity(new NodeType());
520                 break;
521             case DATA_TYPE:
522                 flatData.setFlatEntity(new DataType());
523                 break;
524             default:
525                 throw new SdcRuntimeException("Entity[" + elementType + "] id[" + typeId + "] flat not supported");
526         }
527
528         boolean isEntityFound =
529                 scanAnFlatEntity(elementType, typeId, flatData, serviceTemplate, toscaModel, new ArrayList<>(), 0);
530         if (!isEntityFound) {
531             throw new CoreException(new ToscaElementTypeNotFoundErrorBuilder(typeId).build());
532         }
533
534         return flatData;
535     }
536
537     @Override
538     public boolean isSubstitutableNodeTemplate(NodeTemplate nodeTemplate) {
539         return nodeTemplate.getDirectives() != null && nodeTemplate.getDirectives().contains(
540                 ToscaConstants.NODE_TEMPLATE_DIRECTIVE_SUBSTITUTABLE);
541     }
542
543     private <T> Optional<Boolean> isTypeExistInServiceTemplateHierarchy(String typeToMatch, String typeToSearch,
544             String getTypesMethodName, ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel,
545             Set<String> analyzedImportFiles)
546             throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
547         Map<String, T> searchableTypes =
548                 (Map<String, T>) serviceTemplate.getClass().getMethod(getTypesMethodName).invoke(serviceTemplate);
549
550         if (!MapUtils.isEmpty(searchableTypes)) {
551             T typeObject = searchableTypes.get(typeToSearch);
552             if (Objects.nonNull(typeObject)) {
553                 String derivedFromTypeVal =
554                         (String) typeObject.getClass().getMethod(GET_DERIVED_FROM_METHOD_NAME).invoke(typeObject);
555                 if (Objects.equals(derivedFromTypeVal, typeToMatch)) {
556                     return Optional.of(true);
557                 } else if (Objects.isNull(derivedFromTypeVal) || isTypeIsToscaRoot(derivedFromTypeVal)) {
558                     return Optional.of(false);
559                 } else {
560                     return isTypeExistInServiceTemplateHierarchy(typeToMatch, derivedFromTypeVal, getTypesMethodName,
561                             serviceTemplate, toscaServiceModel, null);
562                 }
563             } else {
564                 return isTypeExistInImports(typeToMatch, typeToSearch, getTypesMethodName, serviceTemplate,
565                         toscaServiceModel, analyzedImportFiles);
566             }
567         }
568         return isTypeExistInImports(typeToMatch, typeToSearch, getTypesMethodName, serviceTemplate, toscaServiceModel,
569                 analyzedImportFiles);
570     }
571
572     private Optional<Boolean> isTypeExistInImports(String typeToMatch, String typeToSearch, String getTypesMethodName,
573             ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel, Set<String> filesScanned)
574             throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
575         List<Map<String, Import>> imports = serviceTemplate.getImports();
576         if (CollectionUtils.isEmpty(imports)) {
577             return Optional.empty();
578         }
579
580         Set<String> createdFilesScanned = createFilesScannedSet(filesScanned);
581
582         for (Map<String, Import> map : imports) {
583             ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
584             Import anImport = toscaExtensionYamlUtil
585                                       .yamlToObject(toscaExtensionYamlUtil.objectToYaml(map.values().iterator().next()),
586                                               Import.class);
587             handleImportWithNoFileEntry(anImport);
588             String importFile = anImport.getFile();
589             ServiceTemplate template = toscaServiceModel.getServiceTemplates()
590                                                         .get(fetchFullFileNameForImport(importFile,
591                                                                 serviceTemplate.getMetadata() == null ? null :
592                                                                         serviceTemplate.getMetadata().get("filename"),
593                                                                 serviceTemplate, toscaServiceModel));
594             if (Objects.isNull(template) || createdFilesScanned
595                                                     .contains(ToscaUtil.getServiceTemplateFileName(template))) {
596                 continue;
597             } else {
598                 createdFilesScanned.add(ToscaUtil.getServiceTemplateFileName(template));
599             }
600             Optional<Boolean> typeExistInServiceTemplateHierarchy =
601                     isTypeExistInServiceTemplateHierarchy(typeToMatch, typeToSearch, getTypesMethodName, template,
602                             toscaServiceModel, createdFilesScanned);
603             if (typeExistInServiceTemplateHierarchy.isPresent() && (typeExistInServiceTemplateHierarchy.get())) {
604                 createdFilesScanned.clear();
605                 return Optional.of(true);
606             }
607
608         }
609         return Optional.of(false);
610     }
611
612     private void handleImportWithNoFileEntry(Import anImport) {
613         if (Objects.isNull(anImport) || Objects.isNull(anImport.getFile())) {
614             throw new SdcRuntimeException("import without file entry");
615         }
616     }
617
618     private Set<String> createFilesScannedSet(Set<String> filesScanned) {
619         Set<String> retFileScanned = filesScanned;
620         if (Objects.isNull(retFileScanned)) {
621             retFileScanned = new HashSet<>();
622         }
623         return retFileScanned;
624     }
625
626     private boolean isTypeIsToscaRoot(String type) {
627         return (type.contains(TOSCA_DOT) && type.contains(DOT_ROOT));
628     }
629
630     private boolean isSubstitutionServiceTemplate(String substituteServiceTemplateFileName,
631             ServiceTemplate substituteServiceTemplate) {
632         if (substituteServiceTemplate != null && substituteServiceTemplate.getTopology_template() != null
633                     && substituteServiceTemplate.getTopology_template().getSubstitution_mappings() != null) {
634             if (substituteServiceTemplate.getTopology_template().getSubstitution_mappings().getNode_type() == null) {
635                 throw new CoreException(
636                         new ToscaInvalidSubstitutionServiceTemplateErrorBuilder(substituteServiceTemplateFileName)
637                                 .build());
638             }
639             return true;
640         }
641         return false;
642
643     }
644
645     private boolean scanAnFlatEntity(ToscaElementTypes elementType, String typeId, ToscaFlatData flatData,
646             ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel, List<String> filesScanned,
647             int rootScanStartInx) {
648
649
650         boolean entityFound =
651                 enrichEntityFromCurrentServiceTemplate(elementType, typeId, flatData, serviceTemplate, toscaModel,
652                         filesScanned, rootScanStartInx);
653         if (!entityFound) {
654             List<Map<String, Import>> imports = serviceTemplate.getImports();
655             if (CollectionUtils.isEmpty(imports)) {
656                 return false;
657             }
658             boolean found = false;
659             for (Map<String, Import> importMap : imports) {
660                 if (found) {
661                     return true;
662                 }
663                 found = isFlatEntity(importMap, flatData, serviceTemplate, filesScanned, toscaModel, elementType,
664                         typeId);
665             }
666             return found;
667         }
668         return true;
669     }
670
671     private boolean isFlatEntity(Map<String, Import> importMap, ToscaFlatData flatData, ServiceTemplate serviceTemplate,
672             List<String> filesScanned, ToscaServiceModel toscaModel, ToscaElementTypes elementType, String typeId) {
673         boolean found = false;
674         ToscaExtensionYamlUtil toscaExtensionYamlUtil = new ToscaExtensionYamlUtil();
675         for (Object importObject : importMap.values()) {
676             Import importServiceTemplate = toscaExtensionYamlUtil
677                                                    .yamlToObject(toscaExtensionYamlUtil.objectToYaml(importObject),
678                                                            Import.class);
679             String fileName = fetchFullFileNameForImport(importServiceTemplate.getFile(),
680                     serviceTemplate.getMetadata() == null ? null : serviceTemplate.getMetadata().get("filename"),
681                     serviceTemplate, toscaModel);
682             if (filesScanned.contains(fileName)) {
683                 return false;
684             } else {
685                 filesScanned.add(fileName);
686             }
687             ServiceTemplate template = toscaModel.getServiceTemplates().get(fileName);
688             if (Objects.isNull(template)) {
689                 throw new CoreException(new ToscaFileNotFoundErrorBuilder(fileName).build());
690             }
691             found = scanAnFlatEntity(elementType, typeId, flatData, template, toscaModel, filesScanned,
692                     filesScanned.size());
693         }
694         return found;
695     }
696
697     String fetchFullFileNameForImport(String importServiceTemplateFile, String currentMetadatafileName,
698             ServiceTemplate serviceTemplate, ToscaServiceModel toscaServiceModel) {
699         Optional<Map.Entry<String, ServiceTemplate>> serviceTemplateEntry =
700                 toscaServiceModel.getServiceTemplates().entrySet().stream()
701                                  .filter(entry -> entry.getValue() == serviceTemplate).findFirst();
702         if (!serviceTemplateEntry.isPresent()) {
703             if (importServiceTemplateFile.contains("../")) {
704                 return importServiceTemplateFile.replace("../", "");
705             } else if (currentMetadatafileName != null && currentMetadatafileName.indexOf('/') != -1) {
706                 return currentMetadatafileName.substring(0, currentMetadatafileName.indexOf('/')) + "/"
707                                + importServiceTemplateFile;
708             } else {
709                 return importServiceTemplateFile;
710             }
711         }
712
713         Path currentPath = Paths.get(serviceTemplateEntry.get().getKey()).getParent();
714         if (currentPath == null) {
715             currentPath = Paths.get("");
716         }
717         return currentPath.resolve(importServiceTemplateFile).normalize().toString().replaceAll("\\\\", "/");
718     }
719
720     private boolean enrichEntityFromCurrentServiceTemplate(ToscaElementTypes elementType, String typeId,
721             ToscaFlatData flatData, ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel,
722             List<String> filesScanned, int rootScanStartInx) {
723         switch (elementType) {
724             case CAPABILITY_TYPE:
725                 if (enrichCapabilityType(elementType, typeId, flatData, serviceTemplate, toscaModel, filesScanned,
726                         rootScanStartInx)) {
727                     return false;
728                 }
729                 break;
730             case NODE_TYPE:
731                 if (enrichNodeTypeInfo(elementType, typeId, flatData, serviceTemplate, toscaModel, filesScanned,
732                         rootScanStartInx)) {
733                     return false;
734                 }
735                 break;
736             case DATA_TYPE:
737                 if (enrichDataTypeInfo(elementType, typeId, flatData, serviceTemplate, toscaModel, filesScanned,
738                         rootScanStartInx)) {
739                     return false;
740                 }
741                 break;
742             default:
743                 throw new SdcRuntimeException("Entity[" + elementType + "] id[" + typeId + "] flat not supported");
744         }
745
746         return true;
747
748
749     }
750
751     private boolean enrichNodeTypeInfo(ToscaElementTypes elementType, String typeId, ToscaFlatData flatData,
752             ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel, List<String> filesScanned,
753             int rootScanStartInx) {
754         String derivedFrom;
755         if (serviceTemplate.getNode_types() != null && serviceTemplate.getNode_types().containsKey(typeId)) {
756
757             filesScanned.clear();
758             flatData.addInheritanceHierarchyType(typeId);
759             NodeType targetNodeType = (NodeType) flatData.getFlatEntity();
760             NodeType sourceNodeType = serviceTemplate.getNode_types().get(typeId);
761             derivedFrom = sourceNodeType.getDerived_from();
762             if (derivedFrom != null) {
763                 boolean isEntityFound =
764                         scanAnFlatEntity(elementType, derivedFrom, flatData, serviceTemplate, toscaModel, filesScanned,
765                                 rootScanStartInx);
766                 if (!isEntityFound) {
767                     throw new CoreException(new ToscaElementTypeNotFoundErrorBuilder(typeId).build());
768                 }
769             }
770             combineNodeTypeInfo(sourceNodeType, targetNodeType);
771         } else {
772             return true;
773         }
774         return false;
775     }
776
777     private boolean enrichDataTypeInfo(ToscaElementTypes elementType, String typeId, ToscaFlatData flatData,
778             ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel, List<String> filesScanned,
779             int rootScanStartInx) {
780         String derivedFrom;
781         if (serviceTemplate.getData_types() != null && serviceTemplate.getData_types().containsKey(typeId)) {
782
783             filesScanned.clear();
784             flatData.addInheritanceHierarchyType(typeId);
785             DataType targetDataType = (DataType) flatData.getFlatEntity();
786             DataType sourceDataType = serviceTemplate.getData_types().get(typeId);
787             derivedFrom = sourceDataType.getDerived_from();
788             if (derivedFrom != null && !isPrimitiveType(derivedFrom)) {
789                 boolean isEntityFound =
790                         scanAnFlatEntity(elementType, derivedFrom, flatData, serviceTemplate, toscaModel, filesScanned,
791                                 rootScanStartInx);
792                 if (!isEntityFound) {
793                     throw new CoreException(new ToscaElementTypeNotFoundErrorBuilder(typeId).build());
794                 }
795             }
796             combineDataTypeInfo(sourceDataType, targetDataType);
797         } else {
798             return true;
799         }
800         return false;
801     }
802
803     private static boolean isPrimitiveType(String toscaType) {
804         return (toscaType.equals(PropertyType.STRING.getDisplayName()) || toscaType.equals(PropertyType.INTEGER
805                                                                                                    .getDisplayName())
806                         || toscaType.equals(PropertyType.FLOAT.getDisplayName()));
807     }
808
809     private boolean enrichCapabilityType(ToscaElementTypes elementType, String typeId, ToscaFlatData flatData,
810             ServiceTemplate serviceTemplate, ToscaServiceModel toscaModel, List<String> filesScanned,
811             int rootScanStartInx) {
812         String derivedFrom;
813         if (serviceTemplate.getCapability_types() != null && serviceTemplate.getCapability_types()
814                                                                             .containsKey(typeId)) {
815
816             filesScanned.clear();
817             flatData.addInheritanceHierarchyType(typeId);
818             CapabilityType targetCapabilityType = (CapabilityType) flatData.getFlatEntity();
819             CapabilityType sourceCapabilityType = serviceTemplate.getCapability_types().get(typeId);
820             derivedFrom = sourceCapabilityType.getDerived_from();
821             if (derivedFrom != null) {
822                 boolean isEntityFound =
823                         scanAnFlatEntity(elementType, derivedFrom, flatData, serviceTemplate, toscaModel, filesScanned,
824                                 rootScanStartInx);
825                 if (!isEntityFound) {
826                     throw new CoreException(new ToscaElementTypeNotFoundErrorBuilder(typeId).build());
827                 }
828             }
829             combineCapabilityTypeInfo(sourceCapabilityType, targetCapabilityType);
830         } else {
831             return true;
832         }
833         return false;
834     }
835
836     private void combineNodeTypeInfo(NodeType sourceNodeType, NodeType targetNodeType) {
837         targetNodeType.setDerived_from(sourceNodeType.getDerived_from());
838         targetNodeType.setDescription(sourceNodeType.getDescription());
839         targetNodeType.setVersion(sourceNodeType.getVersion());
840         targetNodeType
841                 .setProperties(CommonMethods.mergeMaps(targetNodeType.getProperties(), sourceNodeType.getProperties()));
842         combineNodeTypeInterfaceInfo(sourceNodeType, targetNodeType);
843         targetNodeType
844                 .setArtifacts(CommonMethods.mergeMaps(targetNodeType.getArtifacts(), sourceNodeType.getArtifacts()));
845         targetNodeType
846                 .setAttributes(CommonMethods.mergeMaps(targetNodeType.getAttributes(), sourceNodeType.getAttributes()));
847         targetNodeType.setCapabilities(
848                 CommonMethods.mergeMaps(targetNodeType.getCapabilities(), sourceNodeType.getCapabilities()));
849         targetNodeType.setRequirements(
850                 CommonMethods.mergeListsOfMap(targetNodeType.getRequirements(), sourceNodeType.getRequirements()));
851
852     }
853
854     private void combineNodeTypeInterfaceInfo(NodeType sourceNodeType, NodeType targetNodeType) {
855         Optional<Map<String, Object>> interfaceNoMerge = combineInterfaceNoMerge(sourceNodeType, targetNodeType);
856         if (interfaceNoMerge.isPresent()) {
857             targetNodeType.setInterfaces(interfaceNoMerge.get());
858             return;
859         }
860         combineInterfaces(sourceNodeType, targetNodeType).ifPresent(targetNodeType::setInterfaces);
861     }
862
863     private Optional<Map<String, Object>> combineInterfaces(NodeType sourceNodeType, NodeType targetNodeType) {
864         if (MapUtils.isEmpty(sourceNodeType.getInterfaces())) {
865             return Optional.empty();
866         }
867         Map<String, Object> combineInterfaces = new HashMap<>();
868         for (Map.Entry<String, Object> sourceInterfaceDefEntry : sourceNodeType.getInterfaces().entrySet()) {
869             String interfaceName = sourceInterfaceDefEntry.getKey();
870             if (!MapUtils.isEmpty(targetNodeType.getInterfaces()) && targetNodeType.getInterfaces()
871                                                                                    .containsKey(interfaceName)) {
872                 combineInterfaces.put(interfaceName, combineInterfaceDefinition(sourceInterfaceDefEntry.getValue(),
873                         targetNodeType.getInterfaces().get(interfaceName)));
874             } else {
875                 combineInterfaces.put(sourceInterfaceDefEntry.getKey(), sourceInterfaceDefEntry.getValue());
876             }
877         }
878
879         for (Map.Entry<String, Object> targetInterfaceDefEntry : targetNodeType.getInterfaces().entrySet()) {
880             String interfaceName = targetInterfaceDefEntry.getKey();
881             if (!sourceNodeType.getInterfaces().containsKey(interfaceName)) {
882                 combineInterfaces.put(targetInterfaceDefEntry.getKey(), targetInterfaceDefEntry.getValue());
883             }
884         }
885
886         return Optional.of(combineInterfaces);
887     }
888
889     private Optional<Map<String, Object>> combineInterfaceNoMerge(NodeType sourceNodeType, NodeType targetNodeType) {
890         if ((MapUtils.isEmpty(sourceNodeType.getInterfaces()) && MapUtils.isEmpty(targetNodeType.getInterfaces()))) {
891             return Optional.empty();
892         }
893
894         if (MapUtils.isEmpty(sourceNodeType.getInterfaces()) && !MapUtils.isEmpty(targetNodeType.getInterfaces())) {
895             return Optional.of(targetNodeType.getInterfaces());
896         }
897
898         if (!MapUtils.isEmpty(sourceNodeType.getInterfaces()) && MapUtils.isEmpty(targetNodeType.getInterfaces())) {
899             return Optional.of(sourceNodeType.getInterfaces());
900         }
901         return Optional.empty();
902
903     }
904
905     private Object combineInterfaceDefinition(Object sourceInterfaceDefType, Object targetInterfaceDefType) {
906         InterfaceDefinitionType sourceInterface = new InterfaceDefinitionType(sourceInterfaceDefType);
907         InterfaceDefinitionType targetInterface = new InterfaceDefinitionType(targetInterfaceDefType);
908         InterfaceDefinitionType combineInterface = new InterfaceDefinitionType();
909         combineInterface.setType(sourceInterface.getType());
910         combineInterface.setInputs(CommonMethods.mergeMaps(targetInterface.getInputs(), sourceInterface.getInputs()));
911         combineInterface.setOperations(
912                 CommonMethods.mergeMaps(targetInterface.getOperations(), sourceInterface.getOperations()));
913
914         Optional<Object> interfaceDefObject = combineInterface.convertInterfaceDefinitionTypeToToscaObj();
915         if (!interfaceDefObject.isPresent()) {
916             throw new SdcRuntimeException("Illegal Statement");
917         }
918         return interfaceDefObject.get();
919     }
920
921     private void combineDataTypeInfo(DataType sourceDataType, DataType targetDataType) {
922         targetDataType.setDerived_from(sourceDataType.getDerived_from());
923         targetDataType.setDescription(sourceDataType.getDescription());
924         targetDataType.setVersion(sourceDataType.getVersion());
925         targetDataType
926                 .setProperties(CommonMethods.mergeMaps(targetDataType.getProperties(), sourceDataType.getProperties()));
927         targetDataType.setConstraints(
928                 CommonMethods.mergeLists(targetDataType.getConstraints(), sourceDataType.getConstraints()));
929     }
930
931     private void combineCapabilityTypeInfo(CapabilityType sourceCapabilityType, CapabilityType targetCapabilityType) {
932
933         targetCapabilityType.setAttributes(
934                 CommonMethods.mergeMaps(targetCapabilityType.getAttributes(), sourceCapabilityType.getAttributes()));
935         targetCapabilityType.setProperties(
936                 CommonMethods.mergeMaps(targetCapabilityType.getProperties(), sourceCapabilityType.getProperties()));
937         targetCapabilityType.setValid_source_types(CommonMethods
938                                                            .mergeLists(targetCapabilityType.getValid_source_types(),
939                                                                    sourceCapabilityType.getValid_source_types()));
940
941         if (StringUtils.isNotEmpty(sourceCapabilityType.getDerived_from())) {
942             targetCapabilityType.setDerived_from(sourceCapabilityType.getDerived_from());
943         }
944         if (StringUtils.isNotEmpty(sourceCapabilityType.getDescription())) {
945             targetCapabilityType.setDescription(sourceCapabilityType.getDescription());
946         }
947         if (StringUtils.isNotEmpty(sourceCapabilityType.getVersion())) {
948             targetCapabilityType.setVersion(sourceCapabilityType.getVersion());
949         }
950
951
952     }
953
954
955     /*
956      * Create node type according to the input substitution service template, while the substitution
957      * service template can be mappted to this node type, for substitution mapping.
958      *
959      * @param substitutionServiceTemplate  substitution serivce template
960      * @param nodeTypeDerivedFromValue derived from value for the created node type
961      * @return the node type
962      */
963     @Override
964     public NodeType createInitSubstitutionNodeType(ServiceTemplate substitutionServiceTemplate,
965             String nodeTypeDerivedFromValue) {
966         NodeType substitutionNodeType = new NodeType();
967         substitutionNodeType.setDerived_from(nodeTypeDerivedFromValue);
968         substitutionNodeType.setDescription(substitutionServiceTemplate.getDescription());
969         substitutionNodeType.setProperties(manageSubstitutionNodeTypeProperties(substitutionServiceTemplate));
970         substitutionNodeType.setAttributes(manageSubstitutionNodeTypeAttributes(substitutionServiceTemplate));
971         return substitutionNodeType;
972     }
973
974     @Override
975     public Map<String, PropertyDefinition> manageSubstitutionNodeTypeProperties(
976             ServiceTemplate substitutionServiceTemplate) {
977         Map<String, PropertyDefinition> substitutionNodeTypeProperties = new HashMap<>();
978         Map<String, ParameterDefinition> properties = substitutionServiceTemplate.getTopology_template().getInputs();
979         if (properties == null) {
980             return null;
981         }
982
983         PropertyDefinition propertyDefinition;
984         String toscaPropertyName;
985         for (Map.Entry<String, ParameterDefinition> entry : properties.entrySet()) {
986             toscaPropertyName = entry.getKey();
987             propertyDefinition = new PropertyDefinition();
988             ParameterDefinition parameterDefinition =
989                     substitutionServiceTemplate.getTopology_template().getInputs().get(toscaPropertyName);
990             propertyDefinition.setType(parameterDefinition.getType());
991             propertyDefinition.setDescription(parameterDefinition.getDescription());
992             propertyDefinition.set_default(parameterDefinition.get_default());
993             if (parameterDefinition.getRequired() != null) {
994                 propertyDefinition.setRequired(parameterDefinition.getRequired());
995             }
996             if (propertyDefinition.get_default() != null) {
997                 propertyDefinition.setRequired(false);
998             }
999             if (!CollectionUtils.isEmpty(parameterDefinition.getConstraints())) {
1000                 propertyDefinition.setConstraints(parameterDefinition.getConstraints());
1001             }
1002             propertyDefinition.setEntry_schema(parameterDefinition.getEntry_schema());
1003             if (parameterDefinition.getStatus() != null) {
1004                 propertyDefinition.setStatus(parameterDefinition.getStatus());
1005             }
1006             substitutionNodeTypeProperties.put(toscaPropertyName, propertyDefinition);
1007         }
1008         return substitutionNodeTypeProperties;
1009     }
1010
1011
1012     private Map<String, AttributeDefinition> manageSubstitutionNodeTypeAttributes(
1013             ServiceTemplate substitutionServiceTemplate) {
1014         Map<String, AttributeDefinition> substitutionNodeTypeAttributes = new HashMap<>();
1015         Map<String, ParameterDefinition> attributes = substitutionServiceTemplate.getTopology_template().getOutputs();
1016         if (attributes == null) {
1017             return null;
1018         }
1019         AttributeDefinition attributeDefinition;
1020         String toscaAttributeName;
1021
1022         for (Map.Entry<String, ParameterDefinition> entry : attributes.entrySet()) {
1023             attributeDefinition = new AttributeDefinition();
1024             toscaAttributeName = entry.getKey();
1025             ParameterDefinition parameterDefinition =
1026                     substitutionServiceTemplate.getTopology_template().getOutputs().get(toscaAttributeName);
1027             if (parameterDefinition.getType() != null && !parameterDefinition.getType().isEmpty()) {
1028                 attributeDefinition.setType(parameterDefinition.getType());
1029             } else {
1030                 attributeDefinition.setType(PropertyType.STRING.getDisplayName());
1031             }
1032             attributeDefinition.setDescription(parameterDefinition.getDescription());
1033             attributeDefinition.set_default(parameterDefinition.get_default());
1034             attributeDefinition.setEntry_schema(parameterDefinition.getEntry_schema());
1035             if (Objects.nonNull(parameterDefinition.getStatus())) {
1036                 attributeDefinition.setStatus(parameterDefinition.getStatus());
1037             }
1038             substitutionNodeTypeAttributes.put(toscaAttributeName, attributeDefinition);
1039         }
1040         return substitutionNodeTypeAttributes;
1041     }
1042
1043     /**
1044      * Checks if the requirement exists in the node template.
1045      *
1046      * @param nodeTemplate          the node template
1047      * @param requirementId         the requirement id
1048      * @param requirementAssignment the requirement assignment
1049      * @return true if the requirement already exists and false otherwise
1050      */
1051     @Override
1052     public boolean isRequirementExistInNodeTemplate(NodeTemplate nodeTemplate, String requirementId,
1053             RequirementAssignment requirementAssignment) {
1054         List<Map<String, RequirementAssignment>> nodeTemplateRequirements = nodeTemplate.getRequirements();
1055         return nodeTemplateRequirements != null && nodeTemplateRequirements.stream().anyMatch(
1056                 requirement -> requirement.containsKey(requirementId) && DataModelUtil.compareRequirementAssignment(
1057                         requirementAssignment, requirement.get(requirementId)));
1058     }
1059
1060     private <T> boolean isTypeOf(T object, String type, String getTypesMethodName, ServiceTemplate serviceTemplate,
1061             ToscaServiceModel toscaServiceModel) {
1062         if (object == null) {
1063             return false;
1064         }
1065
1066         try {
1067             String objectType = (String) object.getClass().getMethod(GET_TYPE_METHOD_NAME).invoke(object);
1068             if (Objects.equals(objectType, type)) {
1069                 return true;
1070             }
1071
1072             Optional<Boolean> typeExistInServiceTemplateHierarchy =
1073                     isTypeExistInServiceTemplateHierarchy(type, objectType, getTypesMethodName, serviceTemplate,
1074                             toscaServiceModel, null);
1075             return typeExistInServiceTemplateHierarchy.orElseThrow(
1076                     () -> new CoreException(new ToscaElementTypeNotFoundErrorBuilder(objectType).build()));
1077
1078         } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
1079             throw new SdcRuntimeException(e);
1080         }
1081     }
1082 }
1083
1084