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