CPS Delta API: Update action for delta service
[cps.git] / cps-service / src / main / java / org / onap / cps / api / impl / CpsDeltaServiceImpl.java
index 683ddce..1e1fe81 100644 (file)
@@ -28,7 +28,7 @@ import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import lombok.NoArgsConstructor;
+import java.util.Objects;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.api.CpsDeltaService;
 import org.onap.cps.spi.model.DataNode;
@@ -38,7 +38,6 @@ import org.springframework.stereotype.Service;
 
 @Slf4j
 @Service
-@NoArgsConstructor
 public class CpsDeltaServiceImpl implements CpsDeltaService {
 
     @Override
@@ -50,7 +49,7 @@ public class CpsDeltaServiceImpl implements CpsDeltaService {
         final Map<String, DataNode> xpathToSourceDataNodes = convertToXPathToDataNodesMap(sourceDataNodes);
         final Map<String, DataNode> xpathToTargetDataNodes = convertToXPathToDataNodesMap(targetDataNodes);
 
-        deltaReport.addAll(getRemovedDeltaReports(xpathToSourceDataNodes, xpathToTargetDataNodes));
+        deltaReport.addAll(getRemovedAndUpdatedDeltaReports(xpathToSourceDataNodes, xpathToTargetDataNodes));
 
         deltaReport.addAll(getAddedDeltaReports(xpathToSourceDataNodes, xpathToTargetDataNodes));
 
@@ -70,26 +69,122 @@ public class CpsDeltaServiceImpl implements CpsDeltaService {
         return xpathToDataNode;
     }
 
-    private static List<DeltaReport> getRemovedDeltaReports(
-                                                            final Map<String, DataNode> xpathToSourceDataNodes,
-                                                            final Map<String, DataNode> xpathToTargetDataNodes) {
-
-        final List<DeltaReport> removedDeltaReportEntries = new ArrayList<>();
+    private static List<DeltaReport> getRemovedAndUpdatedDeltaReports(
+                                                                final Map<String, DataNode> xpathToSourceDataNodes,
+                                                                final Map<String, DataNode> xpathToTargetDataNodes) {
+        final List<DeltaReport> removedAndUpdatedDeltaReportEntries = new ArrayList<>();
         for (final Map.Entry<String, DataNode> entry: xpathToSourceDataNodes.entrySet()) {
             final String xpath = entry.getKey();
             final DataNode sourceDataNode = entry.getValue();
             final DataNode targetDataNode = xpathToTargetDataNodes.get(xpath);
-
+            final List<DeltaReport> deltaReports;
             if (targetDataNode == null) {
-                final Map<String, Serializable> sourceDataNodeLeaves = sourceDataNode.getLeaves();
-                final DeltaReport removedData = new DeltaReportBuilder().actionRemove().withXpath(xpath)
-                        .withSourceData(sourceDataNodeLeaves).build();
-                removedDeltaReportEntries.add(removedData);
+                deltaReports = getRemovedDeltaReports(xpath, sourceDataNode);
+            } else {
+                deltaReports = getUpdatedDeltaReports(xpath, sourceDataNode, targetDataNode);
             }
+            removedAndUpdatedDeltaReportEntries.addAll(deltaReports);
         }
+        return removedAndUpdatedDeltaReportEntries;
+    }
+
+    private static List<DeltaReport> getRemovedDeltaReports(final String xpath, final DataNode sourceDataNode) {
+        final List<DeltaReport> removedDeltaReportEntries = new ArrayList<>();
+        final Map<String, Serializable> sourceDataNodeLeaves = sourceDataNode.getLeaves();
+        final DeltaReport removedDeltaReportEntry = new DeltaReportBuilder().actionRemove().withXpath(xpath)
+                .withSourceData(sourceDataNodeLeaves).build();
+        removedDeltaReportEntries.add(removedDeltaReportEntry);
         return removedDeltaReportEntries;
     }
 
+    private static List<DeltaReport> getUpdatedDeltaReports(final String xpath, final DataNode sourceDataNode,
+                                                            final DataNode targetDataNode) {
+        final List<DeltaReport> updatedDeltaReportEntries = new ArrayList<>();
+        final Map<Map<String, Serializable>, Map<String, Serializable>> updatedLeavesAsSourceDataToTargetData =
+                getUpdatedLeavesBetweenSourceAndTargetDataNode(sourceDataNode.getLeaves(), targetDataNode.getLeaves());
+        addUpdatedLeavesToDeltaReport(xpath, updatedLeavesAsSourceDataToTargetData, updatedDeltaReportEntries);
+        return updatedDeltaReportEntries;
+    }
+
+    private static Map<Map<String, Serializable>,
+            Map<String, Serializable>> getUpdatedLeavesBetweenSourceAndTargetDataNode(
+                                                            final Map<String, Serializable> leavesOfSourceDataNode,
+                                                            final Map<String, Serializable> leavesOfTargetDataNode) {
+        final Map<Map<String, Serializable>, Map<String, Serializable>> updatedLeavesAsSourceDataToTargetData =
+                new LinkedHashMap<>();
+        final Map<String, Serializable> sourceDataInDeltaReport = new LinkedHashMap<>();
+        final Map<String, Serializable> targetDataInDeltaReport = new LinkedHashMap<>();
+        processLeavesPresentInSourceAndTargetDataNode(leavesOfSourceDataNode, leavesOfTargetDataNode,
+                sourceDataInDeltaReport, targetDataInDeltaReport);
+        processLeavesUniqueInTargetDataNode(leavesOfSourceDataNode, leavesOfTargetDataNode,
+                sourceDataInDeltaReport, targetDataInDeltaReport);
+        final boolean isUpdatedDataInDeltaReport =
+                !sourceDataInDeltaReport.isEmpty() || !targetDataInDeltaReport.isEmpty();
+        if (isUpdatedDataInDeltaReport) {
+            updatedLeavesAsSourceDataToTargetData.put(sourceDataInDeltaReport, targetDataInDeltaReport);
+        }
+        return updatedLeavesAsSourceDataToTargetData;
+    }
+
+    private static void processLeavesPresentInSourceAndTargetDataNode(
+                                                            final Map<String, Serializable> leavesOfSourceDataNode,
+                                                            final Map<String, Serializable> leavesOfTargetDataNode,
+                                                            final Map<String, Serializable> sourceDataInDeltaReport,
+                                                            final Map<String, Serializable> targetDataInDeltaReport) {
+        for (final Map.Entry<String, Serializable> entry: leavesOfSourceDataNode.entrySet()) {
+            final String key = entry.getKey();
+            final Serializable sourceLeaf = entry.getValue();
+            final Serializable targetLeaf = leavesOfTargetDataNode.get(key);
+            compareLeaves(key, sourceLeaf, targetLeaf, sourceDataInDeltaReport, targetDataInDeltaReport);
+        }
+    }
+
+    private static void processLeavesUniqueInTargetDataNode(
+                                                            final Map<String, Serializable> leavesOfSourceDataNode,
+                                                            final Map<String, Serializable> leavesOfTargetDataNode,
+                                                            final Map<String, Serializable> sourceDataInDeltaReport,
+                                                            final Map<String, Serializable> targetDataInDeltaReport) {
+        final Map<String, Serializable> uniqueLeavesOfTargetDataNode =
+                new LinkedHashMap<>(leavesOfTargetDataNode);
+        uniqueLeavesOfTargetDataNode.keySet().removeAll(leavesOfSourceDataNode.keySet());
+        for (final Map.Entry<String, Serializable> entry: uniqueLeavesOfTargetDataNode.entrySet()) {
+            final String key = entry.getKey();
+            final Serializable targetLeaf = entry.getValue();
+            final Serializable sourceLeaf = leavesOfSourceDataNode.get(key);
+            compareLeaves(key, sourceLeaf, targetLeaf, sourceDataInDeltaReport, targetDataInDeltaReport);
+        }
+    }
+
+    private static void compareLeaves(final String key,
+                                      final Serializable sourceLeaf,
+                                      final Serializable targetLeaf,
+                                      final Map<String, Serializable> sourceDataInDeltaReport,
+                                      final Map<String, Serializable> targetDataInDeltaReport) {
+        if (sourceLeaf != null && targetLeaf != null) {
+            if (!Objects.equals(sourceLeaf, targetLeaf)) {
+                sourceDataInDeltaReport.put(key, sourceLeaf);
+                targetDataInDeltaReport.put(key, targetLeaf);
+            }
+        } else if (sourceLeaf != null) {
+            sourceDataInDeltaReport.put(key, sourceLeaf);
+        } else if (targetLeaf != null) {
+            targetDataInDeltaReport.put(key, targetLeaf);
+        }
+    }
+
+    private static void addUpdatedLeavesToDeltaReport(final String xpath,
+                                                      final Map<Map<String, Serializable>, Map<String,
+                                                              Serializable>> updatedLeavesAsSourceDataToTargetData,
+                                                      final List<DeltaReport> updatedDeltaReportEntries) {
+        for (final Map.Entry<Map<String, Serializable>, Map<String, Serializable>> entry:
+                updatedLeavesAsSourceDataToTargetData.entrySet()) {
+            final DeltaReport updatedDataForDeltaReport = new DeltaReportBuilder().actionUpdate()
+                    .withXpath(xpath).withSourceData(entry.getKey()).withTargetData(entry.getValue()).build();
+            updatedDeltaReportEntries.add(updatedDataForDeltaReport);
+        }
+
+    }
+
     private static List<DeltaReport> getAddedDeltaReports(final Map<String, DataNode> xpathToSourceDataNodes,
                                                           final Map<String, DataNode> xpathToTargetDataNodes) {