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