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