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