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