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