aboutsummaryrefslogtreecommitdiffstats
path: root/catalog-be/src/main/java/org/openecomp/sdc/be/components/merge/property/PropertyDataValueMergeBusinessLogic.java
blob: 318840d60ae17670d32248874a9f3462eceeb1dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package org.openecomp.sdc.be.components.merge.property;

import com.google.gson.Gson;
import fj.data.Either;
import org.openecomp.sdc.be.dao.titan.TitanOperationStatus;
import org.openecomp.sdc.be.datatypes.elements.GetInputValueDataDefinition;
import org.openecomp.sdc.be.datatypes.elements.PropertyDataDefinition;
import org.openecomp.sdc.be.model.DataTypeDefinition;
import org.openecomp.sdc.be.model.cache.ApplicationDataTypeCache;
import org.openecomp.sdc.be.model.tosca.ToscaFunctions;
import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
import org.openecomp.sdc.be.tosca.PropertyConvertor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class PropertyDataValueMergeBusinessLogic {

    private static final Logger LOGGER = LoggerFactory.getLogger(PropertyDataValueMergeBusinessLogic.class);

    private final PropertyConvertor propertyConvertor = PropertyConvertor.getInstance();

    private PropertyValueMerger complexPropertyValueMerger = ComplexPropertyValueMerger.getInstance();

    private PropertyValueMerger scalarPropertyValueMerger = ScalarPropertyValueMerger.getInstance();

    @Resource
    private ApplicationDataTypeCache dataTypeCache;

    private final Gson gson = new Gson();

    /**
     *
     * @param oldProp the old property to merge value from
     * @param newProp the new property to merge value into
     * @param getInputNamesToMerge inputs names which their corresponding get_input values are allowed to be merged
     */
    public void mergePropertyValue(PropertyDataDefinition oldProp, PropertyDataDefinition newProp, List<String> getInputNamesToMerge) {
        Either<Map<String, DataTypeDefinition>, TitanOperationStatus> dataTypesEither = dataTypeCache.getAll();
        if (dataTypesEither.isRight()) {
            LOGGER.debug("failed to fetch data types, skip merging of previous property values. status: {}", dataTypesEither.right().value());
        }
        mergePropertyValue(oldProp, newProp, dataTypesEither.left().value(), getInputNamesToMerge);
        mergeComplexPropertyGetInputsValues(oldProp, newProp);
    }

    private void mergePropertyValue(PropertyDataDefinition oldProp, PropertyDataDefinition newProp, Map<String, DataTypeDefinition> dataTypes, List<String> getInputNamesToMerge) {
        Object oldValAsObject = convertPropertyStrValueToObject(oldProp, dataTypes);
        Object newValAsObject = convertPropertyStrValueToObject(newProp, dataTypes);
        PropertyValueMerger propertyValueMerger = getPropertyValueMerger(newProp);
        if(oldValAsObject != null){
            Object mergedValue = propertyValueMerger.mergeValues(oldValAsObject, newValAsObject, getInputNamesToMerge);
            newProp.setValue(convertPropertyValueObjectToString(mergedValue));
        }
    }

    private PropertyValueMerger getPropertyValueMerger(PropertyDataDefinition newProp) {
        if (ToscaPropertyType.isPrimitiveType(newProp.getType()) || ToscaPropertyType.isPrimitiveType(newProp.getSchemaType())) {
            return scalarPropertyValueMerger;
        }
        return complexPropertyValueMerger;
    }

    private String convertPropertyValueObjectToString(Object mergedValue) {
        if (isEmptyValue(mergedValue)) {
            return null;
        }
        return mergedValue instanceof String? mergedValue.toString() : gson.toJson(mergedValue);
    }

    private Object convertPropertyStrValueToObject(PropertyDataDefinition propertyDataDefinition, Map<String, DataTypeDefinition> dataTypes) {
            String propValue = propertyDataDefinition.getValue() == null ? "": propertyDataDefinition.getValue();
            String propertyType = propertyDataDefinition.getType();
            String innerType = propertyDataDefinition.getSchemaType();
            return propertyConvertor.convertToToscaObject(propertyType, propValue, innerType, dataTypes);
    }

    private boolean isEmptyValue(Object val) {
        return val == null ||
               val instanceof Map && ((Map) val).isEmpty() ||
               val instanceof List && ((List) val).isEmpty();
    }

    private void mergeComplexPropertyGetInputsValues(PropertyDataDefinition oldProp, PropertyDataDefinition newProp) {
        if (!oldProp.isGetInputProperty()) {
            return;
        }
        List<GetInputValueDataDefinition> getInputsToMerge = findOldGetInputValuesToMerge(oldProp, newProp);
        List<GetInputValueDataDefinition> newPropGetInputValues = Optional.ofNullable(newProp.getGetInputValues()).orElse(new ArrayList<>());
        newPropGetInputValues.addAll(getInputsToMerge);
        newProp.setGetInputValues(newPropGetInputValues);
    }

    private List<GetInputValueDataDefinition> findOldGetInputValuesToMerge(PropertyDataDefinition oldProp, PropertyDataDefinition newProp) {
        List<GetInputValueDataDefinition> oldGetInputValues = oldProp.getGetInputValues();
        List<GetInputValueDataDefinition> newGetInputValues = Optional.ofNullable(newProp.getGetInputValues()).orElse(Collections.emptyList());
        List<String> newGetInputNames = newGetInputValues.stream().map(GetInputValueDataDefinition::getInputName).collect(Collectors.toList());
        return oldGetInputValues.stream()
                .filter(getInput -> !newGetInputNames.contains(getInput.getInputName()))
                .filter(getInput -> isValueContainsGetInput(getInput.getInputName(), newProp.getValue()))
                .collect(Collectors.toList());
    }

    private boolean isValueContainsGetInput(String inputName, String value) {
        String getInputEntry = "\"%s\":\"%s\"";
        return value != null && value.contains(String.format(getInputEntry, ToscaFunctions.GET_INPUT.getFunctionName(), inputName));
    }










}