48152ea166074b27967138d7059c100f11759968
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / csar / YamlTemplateParsingHandler.java
1 package org.openecomp.sdc.be.components.csar;
2
3 import com.google.common.collect.Lists;
4 import com.google.common.collect.Maps;
5 import com.google.gson.Gson;
6 import fj.data.Either;
7 import org.apache.commons.collections.CollectionUtils;
8 import org.apache.commons.collections.MapUtils;
9 import org.apache.commons.lang.StringUtils;
10 import org.openecomp.sdc.be.components.impl.AnnotationBusinessLogic;
11 import org.openecomp.sdc.be.components.impl.GroupTypeBusinessLogic;
12 import org.openecomp.sdc.be.components.impl.ImportUtils;
13 import org.openecomp.sdc.be.components.impl.NodeFilterUploadCreator;
14 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
15 import org.openecomp.sdc.be.config.BeEcompErrorManager;
16 import org.openecomp.sdc.be.dao.api.ActionStatus;
17 import org.openecomp.sdc.be.dao.jsongraph.TitanDao;
18 import org.openecomp.sdc.be.datatypes.elements.CapabilityDataDefinition;
19 import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition;
20 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
21 import org.openecomp.sdc.be.model.*;
22 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
23 import org.openecomp.sdc.be.utils.TypeUtils;
24 import org.openecomp.sdc.common.log.wrappers.Logger;
25 import org.springframework.stereotype.Component;
26 import org.yaml.snakeyaml.parser.ParserException;
27
28 import java.util.*;
29 import java.util.regex.Pattern;
30 import java.util.stream.Collectors;
31
32 import static java.util.stream.Collectors.toList;
33 import static org.openecomp.sdc.be.components.impl.ImportUtils.*;
34 import static org.openecomp.sdc.be.utils.TypeUtils.ToscaTagNamesEnum.*;
35
36 /**
37  * A handler class designed to parse the YAML file of the service template for a JAVA object
38  */
39 @Component
40 public class YamlTemplateParsingHandler {
41
42     private static final Pattern propertyValuePattern = Pattern.compile("[ ]*\\{[ ]*(str_replace=|token=|get_property=|concat=|get_attribute=)+");
43     private static final int SUB_MAPPING_CAPABILITY_OWNER_NAME_IDX = 0;
44     private static final int SUB_MAPPING_CAPABILITY_NAME_IDX = 1;
45     private static final Logger log = Logger.getLogger(YamlTemplateParsingHandler.class);
46
47
48     private Gson gson = new Gson();
49     private TitanDao titanDao;
50     private GroupTypeBusinessLogic groupTypeBusinessLogic;
51     private AnnotationBusinessLogic annotationBusinessLogic;
52
53     public YamlTemplateParsingHandler(TitanDao titanDao,
54                                       GroupTypeBusinessLogic groupTypeBusinessLogic, AnnotationBusinessLogic annotationBusinessLogic) {
55         this.titanDao = titanDao;
56         this.groupTypeBusinessLogic = groupTypeBusinessLogic;
57         this.annotationBusinessLogic = annotationBusinessLogic;
58     }
59
60     public ParsedToscaYamlInfo parseResourceInfoFromYAML(String fileName, String resourceYml, Map<String, String> createdNodesToscaResourceNames,
61                                                          Map<String, NodeTypeInfo> nodeTypesInfo, String nodeName) {
62         log.debug("#parseResourceInfoFromYAML - Going to parse yaml {} ", fileName);
63         Map<String, Object> mappedToscaTemplate = getMappedToscaTemplate(fileName, resourceYml, nodeTypesInfo, nodeName);
64         ParsedToscaYamlInfo parsedToscaYamlInfo = new ParsedToscaYamlInfo();
65         findToscaElement(mappedToscaTemplate, TOPOLOGY_TEMPLATE, ToscaElementTypeEnum.ALL)
66                 .left()
67                 .on(err -> failIfNotTopologyTemplate(fileName));
68
69         parsedToscaYamlInfo.setInputs(getInputs(mappedToscaTemplate));
70         parsedToscaYamlInfo.setInstances(getInstances(fileName, mappedToscaTemplate, createdNodesToscaResourceNames));
71         parsedToscaYamlInfo.setGroups(getGroups(fileName, mappedToscaTemplate));
72         log.debug("#parseResourceInfoFromYAML - The yaml {} has been parsed ", fileName);
73         return parsedToscaYamlInfo;
74     }
75
76     private Map<String, Object> getMappedToscaTemplate(String fileName, String resourceYml, Map<String, NodeTypeInfo> nodeTypesInfo, String nodeName) {
77         Map<String, Object> mappedToscaTemplate;
78         if (isNodeExist(nodeTypesInfo, nodeName)) {
79             mappedToscaTemplate = nodeTypesInfo.get(nodeName).getMappedToscaTemplate();
80         } else {
81             mappedToscaTemplate = loadYaml(fileName, resourceYml);
82         }
83         return mappedToscaTemplate;
84     }
85
86     private Map<String, Object> loadYaml(String fileName, String resourceYml) {
87         Map<String, Object> mappedToscaTemplate = null;
88         try {
89             mappedToscaTemplate = loadYamlAsStrictMap(resourceYml);
90         } catch (ParserException e) {
91             log.debug("#getMappedToscaTemplate - Failed to load YAML file {}", fileName, e);
92             rollbackWithException(ActionStatus.TOSCA_PARSE_ERROR, fileName, e.getMessage());
93         }
94         return mappedToscaTemplate;
95     }
96
97     private boolean isNodeExist(Map<String, NodeTypeInfo> nodeTypesInfo, String nodeName) {
98         return nodeTypesInfo != null && nodeName != null && nodeTypesInfo.containsKey(nodeName);
99     }
100
101     private Map<String, InputDefinition> getInputs(Map<String, Object> toscaJson) {
102         Map<String, InputDefinition> inputs = ImportUtils.getInputs(toscaJson, annotationBusinessLogic.getAnnotationTypeOperations())
103                 .left()
104                 .on(err -> new HashMap<>());
105         annotationBusinessLogic.validateAndMergeAnnotationsAndAssignToInput(inputs);
106         return inputs;
107     }
108
109     private Map<String, UploadComponentInstanceInfo> getInstances(String yamlName, Map<String, Object> toscaJson, Map<String, String> createdNodesToscaResourceNames) {
110
111         Map<String, Object> nodeTemlates = findFirstToscaMapElement(toscaJson, NODE_TEMPLATES)
112                 .left()
113                 .on(err -> failIfNoNodeTemplates(yamlName));
114
115         Map<String, UploadComponentInstanceInfo> componentInstances = getInstances(toscaJson, createdNodesToscaResourceNames, nodeTemlates);
116         if (MapUtils.isEmpty(componentInstances)) {
117             failIfNotTopologyTemplate(yamlName);
118         }
119         return componentInstances;
120     }
121
122     private Map<String, UploadComponentInstanceInfo> getInstances(Map<String, Object> toscaJson, Map<String, String> createdNodesToscaResourceNames, Map<String, Object> nodeTemlates) {
123         Map<String, UploadComponentInstanceInfo> moduleComponentInstances;
124         Map<String, Object> substitutionMappings = getSubstitutionMappings(toscaJson);
125         moduleComponentInstances = nodeTemlates.entrySet()
126                 .stream()
127                 .map(node -> buildModuleComponentInstanceInfo(node, substitutionMappings, createdNodesToscaResourceNames))
128                 .collect(Collectors.toMap(UploadComponentInstanceInfo::getName, i -> i));
129         return moduleComponentInstances;
130     }
131
132     private Map<String, Object> getSubstitutionMappings(Map<String, Object> toscaJson) {
133         Map<String, Object> substitutionMappings = null;
134         Either<Map<String, Object>, ResultStatusEnum> eitherSubstitutionMappings = findFirstToscaMapElement(toscaJson, SUBSTITUTION_MAPPINGS);
135         if (eitherSubstitutionMappings.isLeft()) {
136             substitutionMappings = eitherSubstitutionMappings.left().value();
137         }
138         return substitutionMappings;
139     }
140
141     @SuppressWarnings("unchecked")
142     private Map<String, GroupDefinition> getGroups(String fileName, Map<String, Object> toscaJson) {
143
144         Map<String, Object> foundGroups = findFirstToscaMapElement(toscaJson, GROUPS)
145                 .left()
146                 .on(err -> logGroupsNotFound(fileName));
147
148         if (MapUtils.isNotEmpty(foundGroups)) {
149             Map<String, GroupDefinition> groups = foundGroups
150                     .entrySet()
151                     .stream()
152                     .map(this::createGroup)
153                     .collect(Collectors.toMap(GroupDefinition::getName, g -> g));
154             Map<String, Object> substitutionMappings = getSubstitutionMappings(toscaJson);
155             if (capabilitiesSubstitutionMappingsExist(substitutionMappings)) {
156                 groups.entrySet().forEach(entry -> updateCapabilitiesNames(entry.getValue(), getNamesToUpdate(entry.getKey(),
157                         (Map<String, List<String>>) substitutionMappings.get(CAPABILITIES.getElementName()))));
158             }
159             return groups;
160         }
161         return new HashMap<>();
162     }
163
164     private Map<String, Object> logGroupsNotFound(String fileName) {
165         log.debug("#logGroupsNotFound - Groups were not found in the yaml template {}.", fileName);
166         return new HashMap<>();
167     }
168
169     private void updateCapabilitiesNames(GroupDefinition group, Map<String, String> capabilityNames) {
170         if (MapUtils.isNotEmpty(group.getCapabilities())) {
171             group.getCapabilities().values()
172                     .stream()
173                     .flatMap(Collection::stream)
174                     .filter(cap -> capabilityNames.containsKey(cap.getName()))
175                     .forEach(cap -> cap.setName(capabilityNames.get(cap.getName())));
176         }
177     }
178
179     private Map<String, String> getNamesToUpdate(String name, Map<String, List<String>> pair) {
180         return pair.entrySet().stream()
181                 .filter(e -> e.getValue().get(SUB_MAPPING_CAPABILITY_OWNER_NAME_IDX).equalsIgnoreCase(name))
182                 .collect(Collectors.toMap(e -> e.getValue().get(SUB_MAPPING_CAPABILITY_NAME_IDX), Map.Entry::getKey,  (n1 ,n2) -> n1));
183     }
184
185     private boolean capabilitiesSubstitutionMappingsExist(Map<String, Object> substitutionMappings) {
186         return substitutionMappings != null && substitutionMappings.containsKey(CAPABILITIES.getElementName());
187     }
188
189     private GroupDefinition createGroup(Map.Entry<String, Object> groupNameValue) {
190         GroupDefinition group = new GroupDefinition();
191         group.setName(groupNameValue.getKey());
192         try {
193             if (groupNameValue.getValue() != null && groupNameValue.getValue() instanceof Map) {
194                 Map<String, Object> groupTemplateJsonMap = (Map<String, Object>) groupNameValue.getValue();
195                 validateAndFillGroup(group, groupTemplateJsonMap);
196                 validateUpdateGroupProperties(group, groupTemplateJsonMap);
197                 validateUpdateGroupCapabilities(group, groupTemplateJsonMap);
198             } else {
199                 rollbackWithException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE);
200             }
201         } catch (ClassCastException e) {
202             log.debug("#createGroup - Failed to create the group {}. The exception occure", groupNameValue.getKey(), e);
203             rollbackWithException(ActionStatus.INVALID_YAML);
204         }
205         return group;
206     }
207
208     private Map<String, CapabilityDefinition> addCapabilities(Map<String, CapabilityDefinition> cap, Map<String, CapabilityDefinition> otherCap) {
209         cap.putAll(otherCap);
210         return cap;
211     }
212
213     private Map<String, CapabilityDefinition> addCapability(CapabilityDefinition cap) {
214         Map<String, CapabilityDefinition> map = Maps.newHashMap();
215         map.put(cap.getName(), cap);
216         return map;
217     }
218
219     private void setMembers(GroupDefinition groupInfo, Map<String, Object> groupTemplateJsonMap) {
220         if (groupTemplateJsonMap.containsKey(MEMBERS.getElementName())) {
221             Object members = groupTemplateJsonMap.get(MEMBERS.getElementName());
222             if (members != null) {
223                 if (members instanceof List) {
224                     setMembersFromList(groupInfo, (List<?>) members);
225                 } else {
226                     log.debug("The 'members' member is not of type list under group {}", groupInfo.getName());
227                     rollbackWithException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE);
228                 }
229             }
230         }
231     }
232
233     private void setMembersFromList(GroupDefinition groupInfo, List<?> membersAsList) {
234         groupInfo.setMembers(membersAsList
235                 .stream()
236                 .collect(Collectors.toMap(Object::toString, member -> "")));
237     }
238
239     @SuppressWarnings("unchecked")
240     private void validateUpdateGroupProperties(GroupDefinition groupInfo, Map<String, Object> groupTemplateJsonMap) {
241         if (groupTemplateJsonMap.containsKey(PROPERTIES.getElementName())) {
242             Object propertiesElement = groupTemplateJsonMap.get(PROPERTIES.getElementName());
243             if (propertiesElement instanceof Map){
244                 mergeGroupProperties(groupInfo, (Map<String, Object>) propertiesElement);
245             }
246         }
247     }
248
249     private void mergeGroupProperties(GroupDefinition groupInfo, Map<String, Object> parsedProperties) {
250         if(CollectionUtils.isNotEmpty(groupInfo.getProperties())){
251             validateGroupProperties(parsedProperties, groupInfo);
252             groupInfo.getProperties().forEach(p -> mergeGroupProperty(p, parsedProperties));
253         }
254     }
255
256     private void mergeGroupProperty(PropertyDataDefinition property, Map<String, Object> parsedProperties) {
257         if(parsedProperties.containsKey(property.getName())){
258             Object propValue = parsedProperties.get(property.getName());
259             if (valueNotContainsPattern(propertyValuePattern, propValue)) {
260                 setPropertyValueAndGetInputsValues(property, propValue);
261             }
262         }
263     }
264
265     private void setPropertyValueAndGetInputsValues(PropertyDataDefinition property, Object propValue) {
266         if(propValue != null){
267             UploadPropInfo uploadPropInfo = buildProperty(property.getName(), propValue);
268             property.setValue(convertPropertyValue(ToscaPropertyType.isValidType(property.getType()), uploadPropInfo.getValue()));
269             property.setGetInputValues(uploadPropInfo.getGet_input());
270         }
271     }
272
273     private String convertPropertyValue(ToscaPropertyType type, Object value) {
274         String convertedValue = null;
275         if (value != null) {
276             if (type == null || value instanceof Map || value instanceof List) {
277                 convertedValue = gson.toJson(value);
278             } else {
279                 convertedValue = value.toString();
280             }
281         }
282         return convertedValue;
283     }
284
285     private void setDescription(GroupDefinition groupInfo, Map<String, Object> groupTemplateJsonMap) {
286         if (groupTemplateJsonMap.containsKey(DESCRIPTION.getElementName())) {
287             groupInfo.setDescription(
288                     (String) groupTemplateJsonMap.get(DESCRIPTION.getElementName()));
289         }
290     }
291
292     private void validateAndFillGroup(GroupDefinition groupInfo, Map<String, Object> groupTemplateJsonMap) {
293         String type = (String) groupTemplateJsonMap.get(TYPE.getElementName());
294         if(StringUtils.isEmpty(type)){
295             log.debug("#validateAndFillGroup - The 'type' member is not found under group {}", groupInfo.getName());
296             rollbackWithException(ActionStatus.GROUP_MISSING_GROUP_TYPE, groupInfo.getName());
297         }
298         groupInfo.setType(type);
299         GroupTypeDefinition groupType =  groupTypeBusinessLogic.getLatestGroupTypeByType(type);
300         if (groupType == null) {
301             log.debug("#validateAndFillGroup - The group type {} not found", groupInfo.getName());
302             rollbackWithException(ActionStatus.GROUP_TYPE_IS_INVALID, type);
303         }
304         groupInfo.convertFromGroupProperties(groupType.getProperties());
305         groupInfo.convertCapabilityDefinitions(groupType.getCapabilities());
306         setDescription(groupInfo, groupTemplateJsonMap);
307         setMembers(groupInfo, groupTemplateJsonMap);
308     }
309
310     @SuppressWarnings("unchecked")
311     private void validateUpdateGroupCapabilities(GroupDefinition groupInfo, Map<String, Object> groupTemplateJsonMap) {
312
313         if (groupTemplateJsonMap.containsKey(CAPABILITIES.getElementName())) {
314             Object capabilities = groupTemplateJsonMap.get(CAPABILITIES.getElementName());
315             if (capabilities instanceof List) {
316                 validateUpdateCapabilities(groupInfo, ((List<Object>) capabilities).stream()
317                         .map(o -> buildGroupCapability(groupInfo, o))
318                         .collect(Collectors.toMap(CapabilityDefinition::getType, this::addCapability, this::addCapabilities)));
319             } else if (capabilities instanceof Map) {
320                 validateUpdateCapabilities(groupInfo, ((Map<String, Object>) capabilities).entrySet()
321                         .stream()
322                         .map(e -> buildGroupCapability(groupInfo, e))
323                         .collect(Collectors.toMap(CapabilityDefinition::getType, this::addCapability, this::addCapabilities)));
324             } else {
325                 log.debug("#setCapabilities - Failed to import the capabilities of the group {}. ", groupInfo.getName());
326                 rollbackWithException(ActionStatus.INVALID_YAML);
327             }
328         }
329     }
330
331     private void validateUpdateCapabilities(GroupDefinition groupInfo, Map<String, Map<String, CapabilityDefinition>> capabilityInfo) {
332         validateGroupCapabilities(groupInfo, capabilityInfo);
333         groupInfo.updateCapabilitiesProperties(capabilityInfo);
334     }
335
336     private void validateGroupCapabilities(GroupDefinition group, Map<String, Map<String, CapabilityDefinition>> parsedCapabilities) {
337         if (MapUtils.isNotEmpty(parsedCapabilities)) {
338             if (MapUtils.isEmpty(group.getCapabilities())) {
339                 failOnMissingCapabilityTypes(group, Lists.newArrayList(parsedCapabilities.keySet()));
340             }
341             List<String> missingCapTypes = parsedCapabilities.keySet().stream().filter(ct -> !group.getCapabilities().containsKey(ct)).collect(toList());
342             if (CollectionUtils.isNotEmpty(missingCapTypes)) {
343                 failOnMissingCapabilityTypes(group, missingCapTypes);
344             }
345             group.getCapabilities().entrySet().forEach(e -> validateCapabilities(group, e.getValue(), parsedCapabilities.get(e.getKey())));
346         }
347     }
348
349     private void validateCapabilities(GroupDefinition group, List<CapabilityDefinition> capabilities, Map<String, CapabilityDefinition> parsedCapabilities) {
350         List<String> allowedCapNames = capabilities.stream().map(CapabilityDefinition::getName).distinct().collect(toList());
351         List<String> missingCapNames = parsedCapabilities.keySet().stream().filter(c -> !allowedCapNames.contains(c)).collect(toList());
352         if (CollectionUtils.isNotEmpty(missingCapNames)) {
353             failOnMissingCapabilityNames(group, missingCapNames);
354         }
355         validateCapabilitiesProperties(capabilities, parsedCapabilities);
356     }
357
358     private void validateCapabilitiesProperties(List<CapabilityDefinition> capabilities, Map<String, CapabilityDefinition> parsedCapabilities) {
359         capabilities.forEach(c -> validateCapabilityProperties(c, parsedCapabilities.get(c.getName())));
360     }
361
362     private void validateCapabilityProperties(CapabilityDefinition capability, CapabilityDefinition parsedCapability) {
363         if(parsedCapability != null && parsedCapability.getProperties() != null){
364             List<String> parsedPropertiesNames = parsedCapability.getProperties()
365                 .stream()
366                 .map(ComponentInstanceProperty::getName).collect(toList());
367             validateProperties(capability.getProperties().stream().map(PropertyDataDefinition::getName).collect(toList()), parsedPropertiesNames, ActionStatus.PROPERTY_NOT_FOUND, capability.getName(), capability.getType());
368         }
369     }
370
371     private void  validateGroupProperties(Map<String, Object> parsedProperties, GroupDefinition groupInfo) {
372         List<String> parsedPropertiesNames = parsedProperties.entrySet()
373                         .stream()
374                         .map(Map.Entry::getKey).collect(toList());
375         validateProperties(groupInfo.getProperties().stream().map(PropertyDataDefinition::getName).collect(toList()), parsedPropertiesNames, ActionStatus.GROUP_PROPERTY_NOT_FOUND, groupInfo.getName(), groupInfo.getType());
376     }
377
378     private void validateProperties(List<String> validProperties, List<String> parsedProperties, ActionStatus actionStatus, String name, String type) {
379         if (CollectionUtils.isNotEmpty(parsedProperties)) {
380             verifyMissingProperties(actionStatus, name, type, parsedProperties
381                     .stream()
382                     .filter(n -> !validProperties.contains(n))
383                     .collect(toList()));
384         }
385     }
386
387     private void verifyMissingProperties(ActionStatus actionStatus, String name, String type, List<String> missingProperties) {
388         if (CollectionUtils.isNotEmpty(missingProperties)) {
389             log.debug("#validateProperties - Failed to validate properties. The properties {} are missing on {} of the type {}. ", missingProperties.toString(), name, type);
390             rollbackWithException(actionStatus, missingProperties.toString(), missingProperties.toString(), name, type);
391         }
392     }
393
394     @SuppressWarnings("unchecked")
395     private CapabilityDefinition buildGroupCapability(GroupDefinition groupInfo, Object capObject) {
396         if (!(capObject instanceof Map)) {
397             log.debug("#convertToGroupCapability - Failed to import the capability {}. ", capObject);
398             rollbackWithException(ActionStatus.INVALID_YAML);
399         }
400         return buildGroupCapability(groupInfo, ((Map<String, Object>) capObject).entrySet().iterator().next());
401     }
402
403     @SuppressWarnings("unchecked")
404     private CapabilityDefinition buildGroupCapability(GroupDefinition groupInfo, Map.Entry<String, Object> capEntry) {
405         CapabilityDefinition capability = new CapabilityDefinition();
406         capability.setOwnerType(CapabilityDataDefinition.OwnerType.GROUP);
407         capability.setName(capEntry.getKey());
408         capability.setParentName(capEntry.getKey());
409         capability.setOwnerId(groupInfo.getName());
410         if (!(capEntry.getValue() instanceof Map)) {
411             log.debug("#convertMapEntryToCapabilityDefinition - Failed to import the capability {}. ", capEntry.getKey());
412             rollbackWithException(ActionStatus.INVALID_YAML);
413         }
414         Map<String, Object> capabilityValue = (Map<String, Object>) capEntry.getValue();
415         String type = (String) capabilityValue.get(TYPE.getElementName());
416         if (StringUtils.isEmpty(type)) {
417             log.debug("#convertMapEntryToCapabilityDefinition - Failed to import the capability {}. Missing capability type. ", capEntry.getKey());
418             rollbackWithException(ActionStatus.INVALID_YAML);
419         }
420         capability.setType(type);
421         if (!(capabilityValue.get(PROPERTIES.getElementName()) instanceof Map)) {
422             log.debug("#convertMapEntryToCapabilityDefinition - Failed to import the capability {}. ", capEntry.getKey());
423             rollbackWithException(ActionStatus.INVALID_YAML);
424         }
425         Map<String, Object> properties = (Map<String, Object>) capabilityValue.get(PROPERTIES.getElementName());
426         capability.setProperties(properties.entrySet().stream().map(this::convertToProperty).collect(toList()));
427         return capability;
428     }
429
430     private ComponentInstanceProperty convertToProperty(Map.Entry<String, Object> e) {
431         ComponentInstanceProperty property = new ComponentInstanceProperty();
432         property.setName(e.getKey());
433         property.setValue((String) e.getValue());
434         return property;
435     }
436
437     @SuppressWarnings("unchecked")
438     private UploadComponentInstanceInfo buildModuleComponentInstanceInfo(
439             Map.Entry<String, Object> nodeTemplateJsonEntry, Map<String, Object> substitutionMappings,
440             Map<String, String> createdNodesToscaResourceNames) {
441
442         UploadComponentInstanceInfo nodeTemplateInfo = new UploadComponentInstanceInfo();
443         nodeTemplateInfo.setName(nodeTemplateJsonEntry.getKey());
444         try {
445             if (nodeTemplateJsonEntry.getValue() instanceof String) {
446                 String nodeTemplateJsonString = (String) nodeTemplateJsonEntry.getValue();
447                 nodeTemplateInfo.setType(nodeTemplateJsonString);
448             } else if (nodeTemplateJsonEntry.getValue() instanceof Map) {
449                 Map<String, Object> nodeTemplateJsonMap = (Map<String, Object>) nodeTemplateJsonEntry.getValue();
450                 setToscaResourceType(createdNodesToscaResourceNames, nodeTemplateInfo, nodeTemplateJsonMap);
451                 setRequirements(nodeTemplateInfo, nodeTemplateJsonMap);
452                 setCapabilities(nodeTemplateInfo, nodeTemplateJsonMap);
453                 updateProperties(nodeTemplateInfo, nodeTemplateJsonMap);
454                 setDirectives(nodeTemplateInfo, nodeTemplateJsonMap);
455                 setNodeFilter(nodeTemplateInfo, nodeTemplateJsonMap);
456                 setSubstitutions(substitutionMappings, nodeTemplateInfo);
457             } else {
458                 rollbackWithException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE);
459             }
460         } catch (ClassCastException e) {
461             BeEcompErrorManager.getInstance().logBeSystemError("Import Resource - create capability");
462             log.debug("error when creating capability, message:{}", e.getMessage(), e);
463             rollbackWithException(ActionStatus.INVALID_YAML);
464         }
465         return nodeTemplateInfo;
466     }
467
468     @SuppressWarnings("unchecked")
469     private void setSubstitutions(Map<String, Object> substitutionMappings, UploadComponentInstanceInfo nodeTemplateInfo) {
470         if (substitutionMappings != null) {
471             if (substitutionMappings.containsKey(CAPABILITIES.getElementName())) {
472                 nodeTemplateInfo.setCapabilitiesNamesToUpdate(getNamesToUpdate(nodeTemplateInfo.getName(), (Map<String, List<String>>) substitutionMappings
473                         .get(CAPABILITIES.getElementName())));
474             }
475             if (substitutionMappings.containsKey(REQUIREMENTS.getElementName())) {
476                 nodeTemplateInfo.setRequirementsNamesToUpdate(getNamesToUpdate(
477                         nodeTemplateInfo.getName(), (Map<String, List<String>>) substitutionMappings
478                                 .get(REQUIREMENTS.getElementName())));
479             }
480         }
481     }
482
483     private void updateProperties(UploadComponentInstanceInfo nodeTemplateInfo, Map<String, Object> nodeTemplateJsonMap) {
484         if (nodeTemplateJsonMap.containsKey(PROPERTIES.getElementName())) {
485             Map<String, List<UploadPropInfo>> properties = buildPropModuleFromYaml(nodeTemplateJsonMap);
486             if (!properties.isEmpty()) {
487                 nodeTemplateInfo.setProperties(properties);
488             }
489         }
490     }
491
492     private void setCapabilities(UploadComponentInstanceInfo nodeTemplateInfo, Map<String, Object> nodeTemplateJsonMap) {
493         if (nodeTemplateJsonMap.containsKey(CAPABILITIES.getElementName())) {
494             Map<String, List<UploadCapInfo>> eitherCapRes = createCapModuleFromYaml(nodeTemplateJsonMap);
495             if (!eitherCapRes.isEmpty()) {
496                 nodeTemplateInfo.setCapabilities(eitherCapRes);
497             }
498         }
499     }
500
501     private void setRequirements(UploadComponentInstanceInfo nodeTemplateInfo, Map<String, Object> nodeTemplateJsonMap) {
502         if (nodeTemplateJsonMap.containsKey(REQUIREMENTS.getElementName())) {
503             Map<String, List<UploadReqInfo>> regResponse = createReqModuleFromYaml(nodeTemplateJsonMap);
504             if (!regResponse.isEmpty()) {
505                 nodeTemplateInfo.setRequirements(regResponse);
506             }
507         }
508     }
509
510     private void setToscaResourceType(Map<String, String> createdNodesToscaResourceNames,
511                                       UploadComponentInstanceInfo nodeTemplateInfo, Map<String, Object> nodeTemplateJsonMap) {
512         if (nodeTemplateJsonMap.containsKey(TYPE.getElementName())) {
513             String toscaResourceType = (String) nodeTemplateJsonMap.get(TYPE.getElementName());
514             if (createdNodesToscaResourceNames.containsKey(toscaResourceType)) {
515                 toscaResourceType = createdNodesToscaResourceNames.get(toscaResourceType);
516             }
517             nodeTemplateInfo.setType(toscaResourceType);
518         }
519     }
520
521     private void setDirectives(UploadComponentInstanceInfo nodeTemplateInfo,
522             Map<String, Object> nodeTemplateJsonMap) {
523         List<String> directives =
524                 (List<String>) nodeTemplateJsonMap.get(TypeUtils.ToscaTagNamesEnum.DIRECTIVES.getElementName());
525         nodeTemplateInfo.setDirectives(directives);
526     }
527
528     private void setNodeFilter(UploadComponentInstanceInfo nodeTemplateInfo,
529             Map<String, Object> nodeTemplateJsonMap) {
530         if (nodeTemplateJsonMap.containsKey(TypeUtils.ToscaTagNamesEnum.NODE_FILTER.getElementName())) {
531             nodeTemplateInfo.setUploadNodeFilterInfo(
532                     new NodeFilterUploadCreator().createNodeFilterData(nodeTemplateJsonMap.get(
533                             TypeUtils.ToscaTagNamesEnum.NODE_FILTER.getElementName())));
534         }
535     }
536
537     @SuppressWarnings("unchecked")
538     private Map<String, List<UploadReqInfo>> createReqModuleFromYaml(Map<String, Object> nodeTemplateJsonMap) {
539         Map<String, List<UploadReqInfo>> moduleRequirements = new HashMap<>();
540         Either<List<Object>, ResultStatusEnum> requirementsListRes =
541                 findFirstToscaListElement(nodeTemplateJsonMap, REQUIREMENTS);
542
543         if (requirementsListRes.isLeft()) {
544             for (Object jsonReqObj : requirementsListRes.left().value()) {
545                 String reqName = ((Map<String, Object>) jsonReqObj).keySet().iterator().next();
546                 Object reqJson = ((Map<String, Object>) jsonReqObj).get(reqName);
547                 addModuleNodeTemplateReq(moduleRequirements, reqJson, reqName);
548             }
549         } else {
550             Either<Map<String, Object>, ResultStatusEnum> requirementsMapRes =
551                     findFirstToscaMapElement(nodeTemplateJsonMap, REQUIREMENTS);
552             if (requirementsMapRes.isLeft()) {
553                 for (Map.Entry<String, Object> entry : requirementsMapRes.left().value().entrySet()) {
554                     String reqName = entry.getKey();
555                     Object reqJson = entry.getValue();
556                     addModuleNodeTemplateReq(moduleRequirements, reqJson, reqName);
557                 }
558             }
559         }
560         return moduleRequirements;
561     }
562
563     private void addModuleNodeTemplateReq(Map<String, List<UploadReqInfo>> moduleRequirements, Object requirementJson, String requirementName) {
564
565         UploadReqInfo requirement = buildModuleNodeTemplateReg(requirementJson);
566         requirement.setName(requirementName);
567         if (moduleRequirements.containsKey(requirementName)) {
568             moduleRequirements.get(requirementName).add(requirement);
569         } else {
570             List<UploadReqInfo> list = new ArrayList<>();
571             list.add(requirement);
572             moduleRequirements.put(requirementName, list);
573         }
574     }
575
576     @SuppressWarnings("unchecked")
577     private Map<String, List<UploadCapInfo>> createCapModuleFromYaml(Map<String, Object> nodeTemplateJsonMap) {
578         Map<String, List<UploadCapInfo>> moduleCap = new HashMap<>();
579         Either<List<Object>, ResultStatusEnum> capabilitiesListRes =
580                 findFirstToscaListElement(nodeTemplateJsonMap, CAPABILITIES);
581         if (capabilitiesListRes.isLeft()) {
582             for (Object jsonCapObj : capabilitiesListRes.left().value()) {
583                 String key = ((Map<String, Object>) jsonCapObj).keySet().iterator().next();
584                 Object capJson = ((Map<String, Object>) jsonCapObj).get(key);
585                 addModuleNodeTemplateCap(moduleCap, capJson, key);
586             }
587         } else {
588             Either<Map<String, Object>, ResultStatusEnum> capabilitiesMapRes =
589                     findFirstToscaMapElement(nodeTemplateJsonMap, CAPABILITIES);
590             if (capabilitiesMapRes.isLeft()) {
591                 for (Map.Entry<String, Object> entry : capabilitiesMapRes.left().value().entrySet()) {
592                     String capName = entry.getKey();
593                     Object capJson = entry.getValue();
594                     addModuleNodeTemplateCap(moduleCap, capJson, capName);
595                 }
596             }
597         }
598         return moduleCap;
599     }
600
601     private void addModuleNodeTemplateCap(Map<String, List<UploadCapInfo>> moduleCap, Object capJson, String key) {
602
603         UploadCapInfo capabilityDef = buildModuleNodeTemplateCap(capJson);
604         capabilityDef.setKey(key);
605         if (moduleCap.containsKey(key)) {
606             moduleCap.get(key).add(capabilityDef);
607         } else {
608             List<UploadCapInfo> list = new ArrayList<>();
609             list.add(capabilityDef);
610             moduleCap.put(key, list);
611         }
612     }
613
614     @SuppressWarnings("unchecked")
615     private UploadCapInfo buildModuleNodeTemplateCap(Object capObject) {
616         UploadCapInfo capTemplateInfo = new UploadCapInfo();
617
618         if (capObject instanceof String) {
619             String nodeTemplateJsonString = (String) capObject;
620             capTemplateInfo.setNode(nodeTemplateJsonString);
621         } else if (capObject instanceof Map) {
622             fillCapability(capTemplateInfo, (Map<String, Object>) capObject);
623         }
624         return capTemplateInfo;
625     }
626
627     private void fillCapability(UploadCapInfo capTemplateInfo, Map<String, Object> nodeTemplateJsonMap) {
628         if (nodeTemplateJsonMap.containsKey(NODE.getElementName())) {
629             capTemplateInfo.setNode((String) nodeTemplateJsonMap.get(NODE.getElementName()));
630         }
631         if (nodeTemplateJsonMap.containsKey(TYPE.getElementName())) {
632             capTemplateInfo.setType((String) nodeTemplateJsonMap.get(TYPE.getElementName()));
633         }
634         if (nodeTemplateJsonMap.containsKey(VALID_SOURCE_TYPES.getElementName())) {
635             Either<List<Object>, ResultStatusEnum> validSourceTypesRes =
636                     findFirstToscaListElement(nodeTemplateJsonMap, VALID_SOURCE_TYPES);
637             if (validSourceTypesRes.isLeft()) {
638                 capTemplateInfo.setValidSourceTypes(validSourceTypesRes.left().value().stream()
639                         .map(Object::toString).collect(toList()));
640             }
641         }
642         if (nodeTemplateJsonMap.containsKey(PROPERTIES.getElementName())) {
643             Map<String, List<UploadPropInfo>> props = buildPropModuleFromYaml(nodeTemplateJsonMap);
644             if (!props.isEmpty()) {
645                 List<UploadPropInfo> properties = props.values().stream().flatMap(Collection::stream).collect(toList());
646                 capTemplateInfo.setProperties(properties);
647             }
648         }
649     }
650
651     @SuppressWarnings("unchecked")
652     private UploadReqInfo buildModuleNodeTemplateReg(Object regObject) {
653
654         UploadReqInfo regTemplateInfo = new UploadReqInfo();
655         if (regObject instanceof String) {
656             String nodeTemplateJsonString = (String) regObject;
657             regTemplateInfo.setNode(nodeTemplateJsonString);
658         } else if (regObject instanceof Map) {
659             Map<String, Object> nodeTemplateJsonMap = (Map<String, Object>) regObject;
660             if (nodeTemplateJsonMap.containsKey(NODE.getElementName())) {
661                 regTemplateInfo.setNode((String) nodeTemplateJsonMap.get(NODE.getElementName()));
662             }
663             if (nodeTemplateJsonMap.containsKey(CAPABILITY.getElementName())) {
664                 regTemplateInfo.setCapabilityName(
665                         (String) nodeTemplateJsonMap.get(CAPABILITY.getElementName()));
666             }
667         }
668         return regTemplateInfo;
669     }
670
671     private Map<String, List<UploadPropInfo>> buildPropModuleFromYaml(Map<String, Object> nodeTemplateJsonMap) {
672
673         Map<String, List<UploadPropInfo>> moduleProp = new HashMap<>();
674         Either<Map<String, Object>, ResultStatusEnum> toscaProperties =
675                 findFirstToscaMapElement(nodeTemplateJsonMap, PROPERTIES);
676         if (toscaProperties.isLeft()) {
677             Map<String, Object> jsonProperties = toscaProperties.left().value();
678             for (Map.Entry<String, Object> jsonPropObj : jsonProperties.entrySet()) {
679                 if (valueNotContainsPattern(propertyValuePattern, jsonPropObj.getValue())) {
680                     addProperty(moduleProp, jsonPropObj);
681                 }
682             }
683         }
684         return moduleProp;
685     }
686
687     private void addProperty(Map<String, List<UploadPropInfo>> moduleProp, Map.Entry<String, Object> jsonPropObj) {
688         UploadPropInfo propertyDef = buildProperty(jsonPropObj.getKey(), jsonPropObj.getValue());
689         if (moduleProp.containsKey(propertyDef.getName())) {
690             moduleProp.get(propertyDef.getName()).add(propertyDef);
691         } else {
692             List<UploadPropInfo> list = new ArrayList<>();
693             list.add(propertyDef);
694             moduleProp.put(propertyDef.getName(), list);
695         }
696     }
697
698     @SuppressWarnings("unchecked")
699     private UploadPropInfo buildProperty(String propName, Object propValue) {
700
701         UploadPropInfo propertyDef = new UploadPropInfo();
702         propertyDef.setValue(propValue);
703         propertyDef.setName(propName);
704         if (propValue instanceof Map) {
705             if (((Map<String, Object>) propValue).containsKey(TYPE.getElementName())) {
706                 propertyDef.setType(((Map<String, Object>) propValue)
707                         .get(TYPE.getElementName()).toString());
708             }
709             if (containsGetInput(propValue)) {
710                 fillInputRecursively(propName, (Map<String, Object>) propValue, propertyDef);
711             }
712
713             if (((Map<String, Object>) propValue).containsKey(DESCRIPTION.getElementName())) {
714                 propertyDef.setDescription(((Map<String, Object>) propValue)
715                         .get(DESCRIPTION.getElementName()).toString());
716             }
717             if (((Map<String, Object>) propValue)
718                     .containsKey(DEFAULT_VALUE.getElementName())) {
719                 propertyDef.setValue(((Map<String, Object>) propValue)
720                         .get(DEFAULT_VALUE.getElementName()));
721             }
722             if (((Map<String, Object>) propValue).containsKey(IS_PASSWORD.getElementName())) {
723                 propertyDef.setPassword(Boolean.getBoolean(((Map<String, Object>) propValue)
724                         .get(IS_PASSWORD.getElementName()).toString()));
725             } else {
726                 propertyDef.setValue(propValue);
727             }
728         } else if (propValue instanceof List) {
729             List<Object> propValueList = (List<Object>) propValue;
730
731             fillInputsListRecursively(propertyDef, propValueList);
732             propertyDef.setValue(propValue);
733         }
734
735         return propertyDef;
736     }
737
738     @SuppressWarnings("unchecked")
739     private boolean containsGetInput(Object propValue) {
740         return ((Map<String, Object>) propValue).containsKey(GET_INPUT.getElementName())
741                 || ImportUtils.containsGetInput(propValue);
742     }
743
744     @SuppressWarnings("unchecked")
745     private void fillInputsListRecursively(UploadPropInfo propertyDef, List<Object> propValueList) {
746         for (Object objValue : propValueList) {
747
748             if (objValue instanceof Map) {
749                 Map<String, Object> objMap = (Map<String, Object>) objValue;
750                 if (objMap.containsKey(GET_INPUT.getElementName())) {
751                     fillInputRecursively(propertyDef.getName(), objMap, propertyDef);
752                 } else {
753                     Set<String> keys = objMap.keySet();
754                     findAndFillInputsListRecursively(propertyDef, objMap, keys);
755                 }
756             } else if (objValue instanceof List) {
757                 List<Object> propSubValueList = (List<Object>) objValue;
758                 fillInputsListRecursively(propertyDef, propSubValueList);
759             }
760         }
761     }
762
763     @SuppressWarnings("unchecked")
764     private void findAndFillInputsListRecursively(UploadPropInfo propertyDef, Map<String, Object> objMap,
765                                                   Set<String> keys) {
766         for (String key : keys) {
767             Object value = objMap.get(key);
768             if (value instanceof Map) {
769                 fillInputRecursively(key, (Map<String, Object>) value, propertyDef);
770             } else if (value instanceof List) {
771                 List<Object> propSubValueList = (List<Object>) value;
772                 fillInputsListRecursively(propertyDef, propSubValueList);
773             }
774         }
775     }
776
777     private void fillInputRecursively(String propName, Map<String, Object> propValue, UploadPropInfo propertyDef) {
778
779         if (propValue.containsKey(GET_INPUT.getElementName())) {
780             Object getInput = propValue.get(GET_INPUT.getElementName());
781             GetInputValueDataDefinition getInputInfo = new GetInputValueDataDefinition();
782             List<GetInputValueDataDefinition> getInputs = propertyDef.getGet_input();
783             if (getInputs == null) {
784                 getInputs = new ArrayList<>();
785             }
786             if (getInput instanceof String) {
787
788                 getInputInfo.setInputName((String) getInput);
789                 getInputInfo.setPropName(propName);
790
791             } else if (getInput instanceof List) {
792                 fillInput(propName, getInput, getInputInfo);
793             }
794             getInputs.add(getInputInfo);
795             propertyDef.setGet_input(getInputs);
796             propertyDef.setValue(propValue);
797         } else {
798             findAndFillInputRecursively(propValue, propertyDef);
799         }
800     }
801
802     @SuppressWarnings("unchecked")
803     private void findAndFillInputRecursively(Map<String, Object> propValue, UploadPropInfo propertyDef) {
804         for (String propName : propValue.keySet()) {
805             Object value = propValue.get(propName);
806             if (value instanceof Map) {
807                 fillInputRecursively(propName, (Map<String, Object>) value, propertyDef);
808
809             } else if (value instanceof List) {
810                 fillInputsRecursively(propertyDef, propName, (List<Object>) value);
811             }
812         }
813     }
814
815     private void fillInputsRecursively(UploadPropInfo propertyDef, String propName, List<Object> inputs) {
816         inputs.stream()
817                 .filter(o -> o instanceof Map)
818                 .forEach(o -> fillInputRecursively(propName, (Map<String, Object>)o, propertyDef));
819     }
820
821     @SuppressWarnings("unchecked")
822     private void fillInput(String propName, Object getInput, GetInputValueDataDefinition getInputInfo) {
823         List<Object> getInputList = (List<Object>) getInput;
824         getInputInfo.setPropName(propName);
825         getInputInfo.setInputName((String) getInputList.get(0));
826         if (getInputList.size() > 1) {
827             Object indexObj = getInputList.get(1);
828             if (indexObj instanceof Integer) {
829                 getInputInfo.setIndexValue((Integer) indexObj);
830             } else if (indexObj instanceof Float) {
831                 int index = ((Float) indexObj).intValue();
832                 getInputInfo.setIndexValue(index);
833             } else if (indexObj instanceof Map && ((Map<String, Object>) indexObj)
834                     .containsKey(GET_INPUT.getElementName())) {
835                 Object index = ((Map<String, Object>) indexObj)
836                         .get(GET_INPUT.getElementName());
837                 GetInputValueDataDefinition getInputInfoIndex = new GetInputValueDataDefinition();
838                 getInputInfoIndex.setInputName((String) index);
839                 getInputInfoIndex.setPropName(propName);
840                 getInputInfo.setGetInputIndex(getInputInfoIndex);
841             }
842             getInputInfo.setList(true);
843         }
844     }
845
846     private boolean valueNotContainsPattern(Pattern pattern, Object propValue) {
847         return propValue == null || !pattern.matcher(propValue.toString()).find();
848     }
849
850     private Map<String, Object> failIfNoNodeTemplates(String fileName) {
851         titanDao.rollback();
852         throw new ComponentException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, fileName);
853     }
854
855     private Object failIfNotTopologyTemplate(String fileName) {
856         titanDao.rollback();
857         throw new ComponentException(ActionStatus.NOT_TOPOLOGY_TOSCA_TEMPLATE, fileName);
858     }
859
860     private void rollbackWithException(ActionStatus actionStatus, String... params) {
861         titanDao.rollback();
862         throw new ComponentException(actionStatus, params);
863     }
864
865     private void failOnMissingCapabilityTypes(GroupDefinition groupDefinition, List<String> missingCapTypes) {
866         log.debug("#failOnMissingCapabilityTypes - Failed to validate the capabilities of the group {}. The capability types {} are missing on the group type {}. ", groupDefinition.getName(), missingCapTypes.toString(), groupDefinition.getType());
867         if(CollectionUtils.isNotEmpty(missingCapTypes)) {
868             rollbackWithException(ActionStatus.MISSING_CAPABILITY_TYPE, missingCapTypes.toString());
869         }
870     }
871
872     private void failOnMissingCapabilityNames(GroupDefinition groupDefinition, List<String> missingCapNames) {
873         log.debug("#failOnMissingCapabilityNames - Failed to validate the capabilities of the group {}. The capabilities with the names {} are missing on the group type {}. ", groupDefinition.getName(), missingCapNames.toString(), groupDefinition.getType());
874         rollbackWithException(ActionStatus.MISSING_CAPABILITIES, missingCapNames.toString(), CapabilityDataDefinition.OwnerType.GROUP.getValue(), groupDefinition.getName());
875     }
876
877 }