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