Sync Integ to Master
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / merge / property / PropertyDataValueMergeBusinessLogic.java
1 package org.openecomp.sdc.be.components.merge.property;
2
3 import com.google.gson.Gson;
4 import fj.data.Either;
5 import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
6 import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition;
7 import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
8 import org.openecomp.sdc.be.model.DataTypeDefinition;
9 import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
10 import org.openecomp.sdc.be.model.tosca.ToscaFunctions;
11 import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
12 import org.openecomp.sdc.be.tosca.PropertyConvertor;
13 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory;
15 import org.springframework.stereotype.Component;
16
17 import javax.annotation.Resource;
18 import java.util.*;
19 import java.util.stream.Collectors;
20
21 @Component
22 public class PropertyDataValueMergeBusinessLogic {
23
24     private static final Logger LOGGER = LoggerFactory.getLogger(PropertyDataValueMergeBusinessLogic.class);
25
26     private final PropertyConvertor propertyConvertor = PropertyConvertor.getInstance();
27
28     private PropertyValueMerger complexPropertyValueMerger = ComplexPropertyValueMerger.getInstance();
29
30     private PropertyValueMerger scalarPropertyValueMerger = ScalarPropertyValueMerger.getInstance();
31
32     @Resource
33     private ApplicationDataTypeCache dataTypeCache;
34
35     private final Gson gson = new Gson();
36
37     /**
38      *
39      * @param oldProp the old property to merge value from
40      * @param newProp the new property to merge value into
41      * @param getInputNamesToMerge inputs names which their corresponding get_input values are allowed to be merged
42      */
43     public void mergePropertyValue(PropertyDataDefinition oldProp, PropertyDataDefinition newProp, List<String> getInputNamesToMerge) {
44         Either<Map<String, DataTypeDefinition>, TitanOperationStatus> dataTypesEither = dataTypeCache.getAll();
45         if (dataTypesEither.isRight()) {
46             LOGGER.debug("failed to fetch data types, skip merging of previous property values. status: {}", dataTypesEither.right().value());
47         }
48         mergePropertyValue(oldProp, newProp, dataTypesEither.left().value(), getInputNamesToMerge);
49         mergeComplexPropertyGetInputsValues(oldProp, newProp);
50     }
51
52     private void mergePropertyValue(PropertyDataDefinition oldProp, PropertyDataDefinition newProp, Map<String, DataTypeDefinition> dataTypes, List<String> getInputNamesToMerge) {
53         Object oldValAsObject = convertPropertyStrValueToObject(oldProp, dataTypes);
54         Object newValAsObject = convertPropertyStrValueToObject(newProp, dataTypes);
55         PropertyValueMerger propertyValueMerger = getPropertyValueMerger(newProp);
56         if(oldValAsObject != null){
57             Object mergedValue = propertyValueMerger.mergeValues(oldValAsObject, newValAsObject, getInputNamesToMerge);
58             newProp.setValue(convertPropertyValueObjectToString(mergedValue));
59         }
60     }
61
62     private PropertyValueMerger getPropertyValueMerger(PropertyDataDefinition newProp) {
63         if (ToscaPropertyType.isPrimitiveType(newProp.getType()) || ToscaPropertyType.isPrimitiveType(newProp.getSchemaType())) {
64             return scalarPropertyValueMerger;
65         }
66         return complexPropertyValueMerger;
67     }
68
69     private String convertPropertyValueObjectToString(Object mergedValue) {
70         if (isEmptyValue(mergedValue)) {
71             return null;
72         }
73         return mergedValue instanceof String? mergedValue.toString() : gson.toJson(mergedValue);
74     }
75
76     private Object convertPropertyStrValueToObject(PropertyDataDefinition propertyDataDefinition, Map<String, DataTypeDefinition> dataTypes) {
77             String propValue = propertyDataDefinition.getValue() == null ? "": propertyDataDefinition.getValue();
78             String propertyType = propertyDataDefinition.getType();
79             String innerType = propertyDataDefinition.getSchemaType();
80             return propertyConvertor.convertToToscaObject(propertyType, propValue, innerType, dataTypes);
81     }
82
83     private boolean isEmptyValue(Object val) {
84         return val == null ||
85                val instanceof Map && ((Map) val).isEmpty() ||
86                val instanceof List && ((List) val).isEmpty();
87     }
88
89     private void mergeComplexPropertyGetInputsValues(PropertyDataDefinition oldProp, PropertyDataDefinition newProp) {
90         if (!oldProp.isGetInputProperty()) {
91             return;
92         }
93         List<GetInputValueDataDefinition> getInputsToMerge = findOldGetInputValuesToMerge(oldProp, newProp);
94         List<GetInputValueDataDefinition> newPropGetInputValues = Optional.ofNullable(newProp.getGetInputValues()).orElse(new ArrayList<>());
95         newPropGetInputValues.addAll(getInputsToMerge);
96         newProp.setGetInputValues(newPropGetInputValues);
97     }
98
99     private List<GetInputValueDataDefinition> findOldGetInputValuesToMerge(PropertyDataDefinition oldProp, PropertyDataDefinition newProp) {
100         List<GetInputValueDataDefinition> oldGetInputValues = oldProp.getGetInputValues();
101         List<GetInputValueDataDefinition> newGetInputValues = Optional.ofNullable(newProp.getGetInputValues()).orElse(Collections.emptyList());
102         List<String> newGetInputNames = newGetInputValues.stream().map(GetInputValueDataDefinition::getInputName).collect(Collectors.toList());
103         return oldGetInputValues.stream()
104                 .filter(getInput -> !newGetInputNames.contains(getInput.getInputName()))
105                 .filter(getInput -> isValueContainsGetInput(getInput.getInputName(), newProp.getValue()))
106                 .collect(Collectors.toList());
107     }
108
109     private boolean isValueContainsGetInput(String inputName, String value) {
110         String getInputEntry = "\"%s\":\"%s\"";
111         return value != null && value.contains(String.format(getInputEntry, ToscaFunctions.GET_INPUT.getFunctionName(), inputName));
112     }
113
114
115
116
117
118
119
120
121
122
123 }