1 package org.openecomp.sdc.be.components.merge.property;
3 import com.google.gson.Gson;
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;
17 import javax.annotation.Resource;
19 import java.util.stream.Collectors;
22 public class PropertyDataValueMergeBusinessLogic {
24 private static final Logger LOGGER = LoggerFactory.getLogger(PropertyDataValueMergeBusinessLogic.class);
26 private final PropertyConvertor propertyConvertor = PropertyConvertor.getInstance();
28 private PropertyValueMerger complexPropertyValueMerger = ComplexPropertyValueMerger.getInstance();
30 private PropertyValueMerger scalarPropertyValueMerger = ScalarPropertyValueMerger.getInstance();
33 private ApplicationDataTypeCache dataTypeCache;
35 private final Gson gson = new Gson();
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
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());
48 mergePropertyValue(oldProp, newProp, dataTypesEither.left().value(), getInputNamesToMerge);
49 mergeComplexPropertyGetInputsValues(oldProp, newProp);
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));
62 private PropertyValueMerger getPropertyValueMerger(PropertyDataDefinition newProp) {
63 if (ToscaPropertyType.isPrimitiveType(newProp.getType()) || ToscaPropertyType.isPrimitiveType(newProp.getSchemaType())) {
64 return scalarPropertyValueMerger;
66 return complexPropertyValueMerger;
69 private String convertPropertyValueObjectToString(Object mergedValue) {
70 if (isEmptyValue(mergedValue)) {
73 return mergedValue instanceof String? mergedValue.toString() : gson.toJson(mergedValue);
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);
83 private boolean isEmptyValue(Object val) {
85 val instanceof Map && ((Map) val).isEmpty() ||
86 val instanceof List && ((List) val).isEmpty();
89 private void mergeComplexPropertyGetInputsValues(PropertyDataDefinition oldProp, PropertyDataDefinition newProp) {
90 if (!oldProp.isGetInputProperty()) {
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);
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());
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));