1 package org.openecomp.sdc.be.components.merge.property;
3 import org.apache.commons.lang.StringUtils;
4 import org.openecomp.sdc.be.components.impl.ImportUtils;
6 import java.util.ArrayList;
9 import java.util.stream.Collectors;
11 public abstract class PropertyValueMerger {
13 abstract Object merge(Object oldVal, Object newVal, List<String> someStrings);
15 @SuppressWarnings("unchecked")
17 * merges property value oldVal into property value newVal recursively
18 * @param oldVal - cannot be {@code Null}
20 protected Object mergeValues(Object oldVal, Object newVal, List<String> getInputNamesToMerge) {
21 if (isEmptyValue(newVal)) {
22 return removeUnwantedGetInputValues(oldVal, getInputNamesToMerge);
24 if (isMapTypeValues(oldVal, newVal)) {
25 return mergeMapValue((Map<String, Object>) oldVal, (Map<String, Object>) newVal, getInputNamesToMerge);
27 if (isListTypeValues(oldVal, newVal)) {
28 return mergeListValue((List<Object>) oldVal, (List<Object>) newVal, getInputNamesToMerge);
30 if (isSameTypeValues(oldVal, newVal)) {
31 return mergeScalarValue(oldVal, newVal);
37 private Map<String, Object> mergeMapValue(Map<String, Object> oldValMap, Map<String, Object> newValMap, List<String> getInputNamesToMerge) {
38 mergeEntriesExistInNewValue(oldValMap, newValMap, getInputNamesToMerge);//continue the recursion
39 setOldEntriesNotExistInNewValue(oldValMap, newValMap, getInputNamesToMerge);
43 private void mergeEntriesExistInNewValue(Map<String, Object> oldValMap, Map<String, Object> newValMap, List<String> getInputNamesToMerge) {
44 for (Map.Entry<String, Object> newValEntry : newValMap.entrySet()) {
45 Object oldVal = oldValMap.get(newValEntry.getKey());
47 newValMap.put(newValEntry.getKey(), merge(oldVal, newValEntry.getValue(), getInputNamesToMerge));
52 private void setOldEntriesNotExistInNewValue(Map<String, Object> oldVal, Map<String, Object> newVal, List<String> getInputNamesToMerge) {
53 for (Map.Entry<String, Object> oldValEntry : oldVal.entrySet()) {
54 if (!isGetInputEntry(oldValEntry) || isGetInputToMerge(getInputNamesToMerge, oldValEntry)) {
55 Object oldValObj = oldValEntry.getValue();
56 newVal.computeIfAbsent(oldValEntry.getKey(), key -> removeUnwantedGetInputValues(oldValObj, getInputNamesToMerge));
61 private List<Object> mergeListValue(List<Object> oldVal, List<Object> newVal, List<String> getInputNamesToMerge) {
62 List<Object> mergedList = mergeLists(oldVal, newVal, getInputNamesToMerge);
63 copyRestOfBiggerList(oldVal, newVal, getInputNamesToMerge, mergedList);
67 private void copyRestOfBiggerList(List<Object> oldVal, List<Object> newVal, List<String> getInputNamesToMerge, List<Object> mergedList) {
68 if (oldVal.size() == newVal.size()) {
71 int maxListSize = Math.max(oldVal.size(), newVal.size());
72 List<Object> greaterList = newVal.size() == maxListSize ? newVal : oldVal;
73 for (int i = mergedList.size(); i < maxListSize; i ++) {
74 Object listVal = greaterList.get(i);
75 Object listValToMerge = greaterList == oldVal ? removeUnwantedGetInputValues(listVal, getInputNamesToMerge) : listVal;
76 mergedList.add(listValToMerge);
80 private List<Object> mergeLists(List<Object> oldVal, List<Object> newVal, List<String> getInputNamesToMerge) {
81 int minListSize = Math.min(oldVal.size(), newVal.size());
82 List<Object> mergedList = new ArrayList<>();
83 for (int i = 0; i < minListSize; i++) {
84 Object mergedVal = merge(oldVal.get(i), newVal.get(i), getInputNamesToMerge);
85 mergedList.add(mergedVal);
90 Object mergeScalarValue(Object oldVal, Object newVal) {
91 return isEmptyValue(newVal) ? oldVal : newVal;
94 @SuppressWarnings("unchecked")
95 Object removeUnwantedGetInputValues(Object val, List<String> getInputNamesToMerge) {
96 if (val instanceof Map) {
97 return removeUnwantedGetInputValues((Map<String, Object>) val, getInputNamesToMerge);
99 if (val instanceof List) {
100 return removeUnwantedGetInputValues((List<Object>)val, getInputNamesToMerge);
105 private List<Object> removeUnwantedGetInputValues(List<Object> listVal, List<String> getInputNamesToMerge) {
106 return listVal.stream().map(val -> removeUnwantedGetInputValues(val, getInputNamesToMerge)).collect(Collectors.toList());
109 private Map<String, Object> removeUnwantedGetInputValues(Map<String, Object> val, List<String> getInputNamesToMerge) {
110 return val.entrySet().stream().filter(entry -> !isGetInputEntry(entry) || isGetInputToMerge(getInputNamesToMerge, entry))
111 .collect(Collectors.toMap(Map.Entry::getKey, entry -> removeUnwantedGetInputValues(entry.getValue(), getInputNamesToMerge)));
114 private boolean isGetInputToMerge(List<String> getInputNamesToMerge, Map.Entry<String, Object> entry) {
115 return getInputNamesToMerge.contains(retrieveGetInputInputName(entry.getValue()));
118 private boolean isMapTypeValues(Object oldVal, Object newVal) {
119 return newVal instanceof Map && oldVal instanceof Map;
122 private boolean isListTypeValues(Object oldVal, Object newVal) {
123 return newVal instanceof List && oldVal instanceof List;
126 private boolean isSameTypeValues(Object oldVal, Object newVal) {
127 return oldVal.getClass().equals(newVal.getClass());
130 private String retrieveGetInputInputName(Object getInputValue) {
131 return getInputValue instanceof List ? (String)((List) getInputValue).get(0) : (String)getInputValue;
134 private boolean isGetInputEntry(Map.Entry<String, Object> oldValEntry) {
135 return oldValEntry.getKey().equals(ImportUtils.ToscaTagNamesEnum.GET_INPUT.getElementName());
138 private boolean isEmptyValue(Object val) {
139 return val == null ||
140 val instanceof String && StringUtils.isEmpty((String)val) ||
141 val instanceof Map && ((Map) val).isEmpty() ||
142 val instanceof List && ((List) val).isEmpty();