re base code
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / merge / property / PropertyValueMerger.java
index 88601bb..93d39cf 100644 (file)
@@ -3,116 +3,154 @@ package org.openecomp.sdc.be.components.merge.property;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Collectors;
 
 import org.apache.commons.lang.StringUtils;
-import org.openecomp.sdc.be.components.impl.ImportUtils;
-
-public abstract class PropertyValueMerger {
-
-    abstract Object merge(Object oldVal, Object newVal, List<String> someStrings);
-
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.openecomp.sdc.be.model.DataTypeDefinition;
+import org.openecomp.sdc.be.model.PropertyDefinition;
+import org.openecomp.sdc.be.model.tosca.ToscaPropertyType;
+import org.openecomp.sdc.be.utils.TypeUtils;
+import org.springframework.stereotype.Component;
+
+@Component
+public class PropertyValueMerger {
+    
     @SuppressWarnings("unchecked")
     /**
      * merges property value oldVal into property value newVal recursively
      * @param oldVal - cannot be {@code Null}
      */
-    protected Object mergeValues(Object oldVal, Object newVal, List<String> getInputNamesToMerge) {
+    protected Object merge(Object oldVal, Object newVal, List<String> inputNamesToMerge, String type, String innerType, Map<String, DataTypeDefinition> dataTypes) {
         if (isEmptyValue(newVal)) {
-            return removeUnwantedGetInputValues(oldVal, getInputNamesToMerge);
+            return removeUnwantedGetInputValues(oldVal, inputNamesToMerge);
         }
         if (isMapTypeValues(oldVal, newVal)) {
-            return mergeMapValue((Map<String, Object>) oldVal, (Map<String, Object>) newVal, getInputNamesToMerge);
+            return mergeMapValue((Map<String, Object>) oldVal, (Map<String, Object>) newVal, inputNamesToMerge, type, innerType, dataTypes);
         }
         if (isListTypeValues(oldVal, newVal)) {
-            return mergeListValue((List<Object>) oldVal, (List<Object>) newVal, getInputNamesToMerge);
+            return mergeListValue((List<Object>) oldVal, (List<Object>) newVal, inputNamesToMerge, innerType, dataTypes);
         }
         if (isSameTypeValues(oldVal, newVal)) {
             return mergeScalarValue(oldVal, newVal);
         }
         return newVal;
-
     }
-
-    private Map<String, Object> mergeMapValue(Map<String, Object> oldValMap, Map<String, Object> newValMap, List<String> getInputNamesToMerge) {
-        mergeEntriesExistInNewValue(oldValMap, newValMap, getInputNamesToMerge);//continue the recursion
-        setOldEntriesNotExistInNewValue(oldValMap, newValMap, getInputNamesToMerge);
+    
+    private Map<String, Object> mergeMapValue(Map<String, Object> oldValMap, Map<String, Object> newValMap, List<String> inputNamesToMerge, String type, String innertType, Map<String, DataTypeDefinition> dataTypes) {
+        mergeEntriesExistInOldValue(oldValMap, newValMap, inputNamesToMerge, type, innertType, dataTypes);//continue the recursion
+        if (type != null && !type.equals("map")) {
+            setOldEntriesNotExistInNewValue(oldValMap, newValMap, inputNamesToMerge);
+        }
+        
         return newValMap;
     }
 
-    private void mergeEntriesExistInNewValue(Map<String, Object> oldValMap, Map<String, Object> newValMap, List<String> getInputNamesToMerge) {
+    private void mergeEntriesExistInOldValue(Map<String, Object> oldValMap, Map<String, Object> newValMap, List<String> inputNamesToMerge, String type, String innerType, Map<String, DataTypeDefinition> dataTypes) {
         for (Map.Entry<String, Object> newValEntry : newValMap.entrySet()) {
             Object oldVal = oldValMap.get(newValEntry.getKey());
             if (oldVal != null) {
-                newValMap.put(newValEntry.getKey(), merge(oldVal, newValEntry.getValue(), getInputNamesToMerge));
+                ImmutablePair<String, String> types = getTypeAndInnerTypePair(newValEntry.getKey(), type, innerType, dataTypes);
+                newValMap.put(newValEntry.getKey(), merge(oldVal, newValEntry.getValue(), inputNamesToMerge, types.getLeft(), types.getRight(), dataTypes));
             }
         }
     }
-
+    
     private void setOldEntriesNotExistInNewValue(Map<String, Object> oldVal, Map<String, Object> newVal, List<String> getInputNamesToMerge) {
         for (Map.Entry<String, Object> oldValEntry : oldVal.entrySet()) {
-            if (!isGetInputEntry(oldValEntry) || isGetInputToMerge(getInputNamesToMerge, oldValEntry)) {
+            if (!isInputEntry(oldValEntry) || isInputToMerge(getInputNamesToMerge, oldValEntry)) {
                 Object oldValObj = oldValEntry.getValue();
                 newVal.computeIfAbsent(oldValEntry.getKey(), key -> removeUnwantedGetInputValues(oldValObj, getInputNamesToMerge));
             }
         }
     }
-
-    private List<Object> mergeListValue(List<Object> oldVal, List<Object> newVal, List<String> getInputNamesToMerge) {
-        List<Object> mergedList = mergeLists(oldVal, newVal, getInputNamesToMerge);
-        copyRestOfBiggerList(oldVal, newVal, getInputNamesToMerge, mergedList);
-        return mergedList;
+    
+    private ImmutablePair<String, String> getTypeAndInnerTypePair(String propName, String type, String innerType, Map<String, DataTypeDefinition> dataTypes) {
+        if (type == null || (ToscaPropertyType.isScalarType(type) && ToscaPropertyType.isScalarType(innerType))) {
+            return ImmutablePair.of(innerType, null);
+        }
+        
+        String newInnerType = null;
+        DataTypeDefinition innerTypeDef = dataTypes.get(type);
+        if (innerTypeDef != null) {
+            List<PropertyDefinition> properties = innerTypeDef.getProperties();
+            if (properties!= null) {
+                Optional<PropertyDefinition> optionalProperty = findProperty(properties, propName);
+                
+                innerType = optionalProperty.map(PropertyDefinition::getType)
+                                            .orElse(innerType);
+                
+                newInnerType = optionalProperty.map(PropertyDefinition::getSchemaType)
+                                               .orElse(null);
+            }
+        }
+                
+        return ImmutablePair.of(innerType, newInnerType);
+    }
+    
+    private Optional<PropertyDefinition> findProperty(List<PropertyDefinition> properties, String propName) {
+        return properties.stream()
+                .filter(p -> propName.equals(p.getName()))
+                .findFirst();
     }
 
-    private void copyRestOfBiggerList(List<Object> oldVal, List<Object> newVal, List<String> getInputNamesToMerge, List<Object> mergedList) {
+    private List<Object> mergeListValue(List<Object> oldVal, List<Object> newVal, List<String> inputNamesToMerge, String innerType, Map<String, DataTypeDefinition> dataTypes) {
+        List<Object> mergedList = newVal;
+    
         if (oldVal.size() == newVal.size()) {
-            return;
-        }
-        int maxListSize = Math.max(oldVal.size(), newVal.size());
-        List<Object> greaterList = newVal.size() == maxListSize ? newVal : oldVal;
-        for (int i = mergedList.size(); i < maxListSize; i ++) {
-            Object listVal = greaterList.get(i);
-            Object listValToMerge = greaterList == oldVal ? removeUnwantedGetInputValues(listVal, getInputNamesToMerge) : listVal;
-            mergedList.add(listValToMerge);
+            mergedList = mergeLists(oldVal, newVal, inputNamesToMerge, innerType, dataTypes);
         }
+
+        return mergedList;
     }
+    
 
-    private List<Object> mergeLists(List<Object> oldVal, List<Object> newVal, List<String> getInputNamesToMerge) {
+    private List<Object> mergeLists(List<Object> oldVal, List<Object> newVal, List<String> inputNamesToMerge, String innerType, Map<String, DataTypeDefinition> dataTypes) {
         int minListSize = Math.min(oldVal.size(), newVal.size());
         List<Object> mergedList = new ArrayList<>();
         for (int i = 0; i < minListSize; i++) {
-            Object mergedVal = merge(oldVal.get(i), newVal.get(i), getInputNamesToMerge);
+            Object mergedVal = merge(oldVal.get(i), newVal.get(i), inputNamesToMerge, innerType, null, dataTypes);
             mergedList.add(mergedVal);
         }
         return mergedList;
     }
-
-    Object mergeScalarValue(Object oldVal, Object newVal) {
+    
+    
+    private Object mergeScalarValue(Object oldVal, Object newVal) {
         return isEmptyValue(newVal) ? oldVal : newVal;
     }
+    
+    static boolean isEmptyValue(Object val) {
+        return val == null ||
+               val instanceof String && StringUtils.isEmpty((String)val) ||
+               val instanceof Map && ((Map<?,?>) val).isEmpty() ||
+               val instanceof List && ((List<?>) val).isEmpty();
 
+    }
+    
     @SuppressWarnings("unchecked")
-    Object removeUnwantedGetInputValues(Object val, List<String> getInputNamesToMerge) {
+    Object removeUnwantedGetInputValues(Object val, List<String> inputNamesToMerge) {
         if (val instanceof  Map) {
-            return removeUnwantedGetInputValues((Map<String, Object>) val, getInputNamesToMerge);
+            return removeUnwantedGetInputValues((Map<String, Object>) val, inputNamesToMerge);
         }
         if (val instanceof List) {
-            return removeUnwantedGetInputValues((List<Object>)val, getInputNamesToMerge);
+            return removeUnwantedGetInputValues((List<Object>)val, inputNamesToMerge);
         }
         return val;
     }
 
-    private List<Object> removeUnwantedGetInputValues(List<Object> listVal, List<String> getInputNamesToMerge) {
-        return listVal.stream().map(val -> removeUnwantedGetInputValues(val, getInputNamesToMerge)).collect(Collectors.toList());
+    private List<Object> removeUnwantedGetInputValues(List<Object> listVal, List<String> inputNamesToMerge) {
+        return listVal.stream().map(val -> removeUnwantedGetInputValues(val, inputNamesToMerge)).collect(Collectors.toList());
     }
 
-    private Map<String, Object> removeUnwantedGetInputValues(Map<String, Object> val, List<String> getInputNamesToMerge) {
-        return val.entrySet().stream().filter(entry -> !isGetInputEntry(entry) || isGetInputToMerge(getInputNamesToMerge, entry))
-                .collect(Collectors.toMap(Map.Entry::getKey, entry -> removeUnwantedGetInputValues(entry.getValue(), getInputNamesToMerge)));
+    private Map<String, Object> removeUnwantedGetInputValues(Map<String, Object> val, List<String> inputNamesToMerge) {
+        return val.entrySet().stream().filter(entry -> !isInputEntry(entry) || isInputToMerge(inputNamesToMerge, entry))
+                .collect(Collectors.toMap(Map.Entry::getKey, entry -> removeUnwantedGetInputValues(entry.getValue(), inputNamesToMerge)));
     }
 
-    private boolean isGetInputToMerge(List<String> getInputNamesToMerge, Map.Entry<String, Object> entry) {
-        return getInputNamesToMerge.contains(retrieveGetInputInputName(entry.getValue()));
+    private boolean isInputToMerge(List<String> inputNamesToMerge, Map.Entry<String, Object> entry) {
+        return inputNamesToMerge.contains(retrieveInputName(entry.getValue()));
     }
 
     private boolean isMapTypeValues(Object oldVal, Object newVal) {
@@ -127,22 +165,13 @@ public abstract class PropertyValueMerger {
         return oldVal.getClass().equals(newVal.getClass());
     }
 
-    private String retrieveGetInputInputName(Object getInputValue) {
-        return getInputValue instanceof List ? (String)((List) getInputValue).get(0) : (String)getInputValue;
-    }
-
-    private boolean isGetInputEntry(Map.Entry<String, Object> oldValEntry) {
-        return oldValEntry.getKey().equals(ImportUtils.ToscaTagNamesEnum.GET_INPUT.getElementName());
+    private String retrieveInputName(Object inputValue) {
+        return inputValue instanceof List ? (String)((List<?>) inputValue).get(0) : (String)inputValue;
     }
 
-    private boolean isEmptyValue(Object val) {
-        return val == null ||
-               val instanceof String && StringUtils.isEmpty((String)val) ||
-               val instanceof Map && ((Map) val).isEmpty() ||
-               val instanceof List && ((List) val).isEmpty();
-
-
+    protected boolean isInputEntry(Map.Entry<String, Object> oldValEntry) {
+        return oldValEntry.getKey().equals(TypeUtils.ToscaTagNamesEnum.GET_INPUT.getElementName());
     }
-
-
+    
+    
 }