Support Policy updates between PAP and PDPs

Change to send only the policies that need to be updated (deployed/undeployed)
rather than full of policies to DMaap via the PDP_UPDATE message

Issue-ID: POLICY-2112
Change-Id: I65f8bf46f230afb9d4b6937cb89af1d9f05d2fbd
Signed-off-by: waynedunican <wayne.dunican@est.tech>
diff --git a/main/src/main/java/org/onap/policy/pap/main/comm/PdpMessageGenerator.java b/main/src/main/java/org/onap/policy/pap/main/comm/PdpMessageGenerator.java
index fb47e92..99408eb 100644
--- a/main/src/main/java/org/onap/policy/pap/main/comm/PdpMessageGenerator.java
+++ b/main/src/main/java/org/onap/policy/pap/main/comm/PdpMessageGenerator.java
@@ -72,7 +72,6 @@
      */
     private final Long heartBeatMs;
 
-
     /**
      * Constructs the object.
      *
@@ -94,21 +93,33 @@
     }
 
     protected PdpUpdate createPdpUpdateMessage(final String pdpGroupName, final PdpSubGroup subGroup,
-        final String pdpInstanceId, final PolicyModelsProvider databaseProvider)
-        throws PfModelException {
+                    final String pdpInstanceId, final PolicyModelsProvider databaseProvider,
+                    final List<ToscaPolicy> policies, final List<ToscaPolicy> policiesToBeDeployed,
+                    final List<ToscaConceptIdentifier> policiesToBeUndeployed) throws PfModelException {
 
         final PdpUpdate update = new PdpUpdate();
+
         update.setName(pdpInstanceId);
         update.setPdpGroup(pdpGroupName);
         update.setPdpSubgroup(subGroup.getPdpType());
-        update.setPolicies(getToscaPolicies(subGroup, databaseProvider));
+        update.setPolicies(policies);
+        update.setPoliciesToBeDeployed(policiesToBeDeployed);
+        update.setPoliciesToBeUndeployed(policiesToBeUndeployed);
         update.setPdpHeartbeatIntervalMs(heartBeatMs);
 
         LOGGER.debug("Created PdpUpdate message - {}", update);
         return update;
     }
 
-    private List<ToscaPolicy> getToscaPolicies(final PdpSubGroup subGroup, final PolicyModelsProvider databaseProvider)
+    /**
+     * Method to return a list of policies.
+     *
+     * @param subGroup PdpSubGroup to retrieve policies from
+     * @param databaseProvider PolicyModelsProvider used to retrieve list of policies
+     * @returns a list of ToscaPolicy
+     **/
+    public List<ToscaPolicy> getToscaPolicies(final PdpSubGroup subGroup,
+            final PolicyModelsProvider databaseProvider)
                     throws PfModelException {
 
         final List<ToscaPolicy> policies = new LinkedList<>();
diff --git a/main/src/main/java/org/onap/policy/pap/main/comm/PdpStatusMessageHandler.java b/main/src/main/java/org/onap/policy/pap/main/comm/PdpStatusMessageHandler.java
index 2e9adda..b692a2a 100644
--- a/main/src/main/java/org/onap/policy/pap/main/comm/PdpStatusMessageHandler.java
+++ b/main/src/main/java/org/onap/policy/pap/main/comm/PdpStatusMessageHandler.java
@@ -23,9 +23,13 @@
 package org.onap.policy.pap.main.comm;
 
 import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.onap.policy.common.utils.services.Registry;
 import org.onap.policy.models.base.PfModelException;
@@ -39,6 +43,8 @@
 import org.onap.policy.models.pdp.concepts.PdpUpdate;
 import org.onap.policy.models.pdp.enums.PdpState;
 import org.onap.policy.models.provider.PolicyModelsProvider;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
 import org.onap.policy.pap.main.PapConstants;
 import org.onap.policy.pap.main.PolicyPapException;
 import org.onap.policy.pap.main.parameters.PdpParameters;
@@ -57,6 +63,21 @@
     private final PdpParameters params;
 
     /**
+     * List to store policies present in db.
+     */
+    List<ToscaPolicy> policies = new LinkedList<>();
+
+    /**
+     * List to store policies to be deployed (heartbeat).
+     */
+    Map<ToscaConceptIdentifier, ToscaPolicy> policiesToBeDeployed = new HashMap<>();
+
+    /**
+     * List to store policies to be undeployed (heartbeat).
+     */
+    List<ToscaConceptIdentifier> policiesToBeUndeployed = new LinkedList<>();
+
+    /**
      * Constructs the object.
      *
      * @param params PDP parameters
@@ -129,6 +150,12 @@
         Optional<PdpSubGroup> subGroup;
         boolean pdpGroupFound = false;
         subGroup = findPdpSubGroup(message, finalizedPdpGroup);
+
+        policies = getToscaPolicies(subGroup.get(), databaseProvider);
+        policiesToBeDeployed = policies.stream().collect(Collectors
+                .toMap(ToscaPolicy::getIdentifier, policy -> policy));
+        policiesToBeUndeployed = null;
+
         if (subGroup.isPresent()) {
             LOGGER.debug("Found pdpGroup - {}, going for registration of PDP - {}", finalizedPdpGroup, message);
             if (!findPdpInstance(message, subGroup.get()).isPresent()) {
@@ -201,7 +228,19 @@
     }
 
     private void processPdpDetails(final PdpStatus message, final PdpSubGroup pdpSubGroup, final Pdp pdpInstance,
-            final PdpGroup pdpGroup, final PolicyModelsProvider databaseProvider) throws PfModelException {
+            final PdpGroup pdpGroup, final PolicyModelsProvider databaseProvider)
+                    throws PfModelException {
+        // all policies
+        policies = getToscaPolicies(pdpSubGroup, databaseProvider);
+
+        // all (-) policies that the PDP already has
+        policiesToBeDeployed.keySet().removeAll(message.getPolicies());
+
+        // policies that the PDP already has (-) all
+        policiesToBeUndeployed = message.getPolicies();
+        policiesToBeUndeployed.removeAll(policies.stream().map(ToscaPolicy::getIdentifier)
+                .collect(Collectors.toList()));
+
         if (PdpState.TERMINATED.equals(message.getState())) {
             processPdpTermination(pdpSubGroup, pdpInstance, pdpGroup, databaseProvider);
         } else if (validatePdpDetails(message, pdpGroup, pdpSubGroup, pdpInstance)) {
@@ -280,9 +319,12 @@
     }
 
     private void sendPdpMessage(final String pdpGroupName, final PdpSubGroup subGroup, final String pdpInstanceId,
-            final PdpState pdpState, final PolicyModelsProvider databaseProvider) throws PfModelException {
+            final PdpState pdpState, final PolicyModelsProvider databaseProvider)
+                    throws PfModelException {
+        final List<ToscaPolicy> polsToBeDeployed = new LinkedList<>(policiesToBeDeployed.values());
         final PdpUpdate pdpUpdatemessage =
-            createPdpUpdateMessage(pdpGroupName, subGroup, pdpInstanceId, databaseProvider);
+            createPdpUpdateMessage(pdpGroupName, subGroup, pdpInstanceId, databaseProvider, policies,
+                        polsToBeDeployed, policiesToBeUndeployed);
         final PdpStateChange pdpStateChangeMessage =
             createPdpStateChangeMessage(pdpGroupName, subGroup, pdpInstanceId, pdpState);
         updateDeploymentStatus(pdpGroupName, subGroup.getPdpType(), pdpInstanceId, pdpStateChangeMessage.getState(),
diff --git a/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateReq.java b/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateReq.java
index 4b5b7f0..18ae5af 100644
--- a/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateReq.java
+++ b/main/src/main/java/org/onap/policy/pap/main/comm/msgdata/UpdateReq.java
@@ -24,7 +24,9 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
 import lombok.Getter;
@@ -125,7 +127,36 @@
             return true;
         }
 
-        reconfigure2(newMessage);
+        Map<ToscaConceptIdentifier, ToscaPolicy> newDeployMap = update.getPoliciesToBeDeployed().stream()
+                .collect(Collectors.toMap(ToscaPolicy::getIdentifier, policy -> policy));
+
+        // Merge full lists
+        final List<ToscaPolicy> fullPolicies = update.getPolicies();
+
+        // Merge undpeloy lists
+        Set<ToscaConceptIdentifier> policiesToBeUndeployedSet = new HashSet<>(getMessage().getPoliciesToBeUndeployed());
+        policiesToBeUndeployedSet.removeAll(newDeployMap.keySet());
+        policiesToBeUndeployedSet.addAll(update.getPoliciesToBeUndeployed());
+        final List<ToscaConceptIdentifier> policiestoBeUndeployed = new LinkedList<>(policiesToBeUndeployedSet);
+
+        // Merge deploy lists
+        final List<ToscaPolicy> policiesToBeDeployed;
+        if (update.getPoliciesToBeDeployed() == update.getPolicies()) {
+            policiesToBeDeployed = update.getPoliciesToBeDeployed();
+        } else {
+            Map<ToscaConceptIdentifier, ToscaPolicy> policiesToBeDeployedMap = getMessage().getPoliciesToBeDeployed()
+                    .stream().collect(Collectors.toMap(ToscaPolicy::getIdentifier, policy -> policy));
+            policiesToBeDeployedMap.keySet().removeAll(update.getPoliciesToBeUndeployed());
+            policiesToBeDeployedMap.putAll(newDeployMap);
+            policiesToBeDeployed = new LinkedList<>(policiesToBeDeployedMap.values());
+        }
+
+        // Set lists in update
+        update.setPolicies(fullPolicies);
+        update.setPoliciesToBeDeployed(policiesToBeDeployed);
+        update.setPoliciesToBeUndeployed(policiestoBeUndeployed);
+
+        reconfigure2(update);
         return true;
     }
 
@@ -144,7 +175,23 @@
         Set<ToscaPolicy> set1 = new HashSet<>(alwaysList(first.getPolicies()));
         Set<ToscaPolicy> set2 = new HashSet<>(alwaysList(second.getPolicies()));
 
-        return set1.equals(set2);
+        if (!(set1.equals(set2))) {
+            return false;
+        }
+
+        Map<ToscaConceptIdentifier, ToscaPolicy> dep1 = first.getPolicies().stream()
+                .collect(Collectors.toMap(ToscaPolicy::getIdentifier, p -> p));
+        Map<ToscaConceptIdentifier, ToscaPolicy> dep2 = second.getPoliciesToBeDeployed()
+                .stream().collect(Collectors.toMap(ToscaPolicy::getIdentifier, p -> p));
+
+        if (!(dep1.equals(dep2))) {
+            return false;
+        }
+
+        HashSet<ToscaConceptIdentifier> undep1 = new HashSet<>(alwaysList(first.getPoliciesToBeUndeployed()));
+        HashSet<ToscaConceptIdentifier> undep2 = new HashSet<>(alwaysList(second.getPoliciesToBeUndeployed()));
+
+        return undep1.equals(undep2);
     }
 
     /**
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeployProvider.java b/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeployProvider.java
index 3c8ce4c..56d2ad3 100644
--- a/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeployProvider.java
+++ b/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupDeployProvider.java
@@ -262,11 +262,11 @@
             return false;
         }
 
-
         Set<String> pdps = dbsub.getPdpInstances().stream().map(Pdp::getInstanceId).collect(Collectors.toSet());
 
         for (ToscaConceptIdentifier policyId : deployed) {
-            data.trackDeploy(policyId, pdps, pdpGroup, dbsub.getPdpType());
+            ToscaPolicy policyToBeDeployed = data.getPolicy(new ToscaConceptIdentifierOptVersion(policyId));
+            data.trackDeploy(policyToBeDeployed, pdps, pdpGroup, dbsub.getPdpType());
         }
 
         for (ToscaConceptIdentifier policyId : undeployed) {
@@ -443,7 +443,8 @@
                             subgroup.getPdpType(), subgroup.getPolicies().size());
 
             Set<String> pdps = subgroup.getPdpInstances().stream().map(Pdp::getInstanceId).collect(Collectors.toSet());
-            data.trackDeploy(desiredIdent, pdps, group.getName(), subgroup.getPdpType());
+            ToscaPolicy policyToBeDeployed = data.getPolicy(new ToscaConceptIdentifierOptVersion(desiredIdent));
+            data.trackDeploy(policyToBeDeployed, pdps, group.getName(), subgroup.getPdpType());
 
             return true;
         };
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupStateChangeProvider.java b/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupStateChangeProvider.java
index 374b528..abea696 100644
--- a/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupStateChangeProvider.java
+++ b/main/src/main/java/org/onap/policy/pap/main/rest/PdpGroupStateChangeProvider.java
@@ -34,6 +34,7 @@
 import org.onap.policy.models.pdp.concepts.PdpUpdate;
 import org.onap.policy.models.pdp.enums.PdpState;
 import org.onap.policy.models.provider.PolicyModelsProvider;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
 import org.onap.policy.pap.main.comm.PdpMessageGenerator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -117,10 +118,12 @@
         final PolicyModelsProvider databaseProvider) throws PfModelException {
         String pdpGroupName = pdpGroup.getName();
         for (final PdpSubGroup subGroup : pdpGroup.getPdpSubgroups()) {
+            List<ToscaPolicy> policies = getToscaPolicies(subGroup, databaseProvider);
             for (final Pdp pdp : subGroup.getPdpInstances()) {
                 String pdpInstanceId = pdp.getInstanceId();
                 final PdpUpdate pdpUpdatemessage =
-                    createPdpUpdateMessage(pdpGroupName, subGroup, pdpInstanceId, databaseProvider);
+                    createPdpUpdateMessage(pdpGroup.getName(), subGroup, pdp.getInstanceId(), databaseProvider,
+                                policies, policies, null);
                 final PdpStateChange pdpStateChangeMessage =
                     createPdpStateChangeMessage(pdpGroupName, subGroup, pdpInstanceId, pdpState);
                 updateDeploymentStatus(pdpGroupName, subGroup.getPdpType(), pdpInstanceId,
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/ProviderBase.java b/main/src/main/java/org/onap/policy/pap/main/rest/ProviderBase.java
index 7f013ac..d64d4e3 100644
--- a/main/src/main/java/org/onap/policy/pap/main/rest/ProviderBase.java
+++ b/main/src/main/java/org/onap/policy/pap/main/rest/ProviderBase.java
@@ -74,7 +74,6 @@
      */
     private final PolicyModelsProviderFactoryWrapper daoFactory;
 
-
     /**
      * Constructs the object.
      */
@@ -182,7 +181,8 @@
      * @param updater function to update a group
      * @throws PfModelException if an error occurred
      */
-    private void upgradeGroup(SessionData data, PdpGroup group, Updater updater) throws PfModelException {
+    private void upgradeGroup(SessionData data, PdpGroup group, Updater updater)
+                    throws PfModelException {
 
         boolean updated = false;
 
@@ -197,7 +197,6 @@
             makeUpdates(data, group, subgroup);
         }
 
-
         if (updated) {
             // something changed
             data.update(group);
@@ -236,6 +235,8 @@
         update.setPdpSubgroup(subgroup.getPdpType());
         update.setPolicies(subgroup.getPolicies().stream().map(ToscaConceptIdentifierOptVersion::new)
                         .map(ident -> getPolicy(data, ident)).collect(Collectors.toList()));
+        update.setPoliciesToBeDeployed(data.getPoliciesToBeDeployed());
+        update.setPoliciesToBeUndeployed(data.getPoliciesToBeUndeployed());
 
         return update;
     }
diff --git a/main/src/main/java/org/onap/policy/pap/main/rest/SessionData.java b/main/src/main/java/org/onap/policy/pap/main/rest/SessionData.java
index b9807c7..c8cddbb 100644
--- a/main/src/main/java/org/onap/policy/pap/main/rest/SessionData.java
+++ b/main/src/main/java/org/onap/policy/pap/main/rest/SessionData.java
@@ -25,8 +25,11 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.tuple.Pair;
 import org.onap.policy.models.base.PfModelException;
@@ -91,6 +94,16 @@
     private final Map<ToscaConceptIdentifier, ToscaPolicyType> typeCache = new HashMap<>();
 
     /**
+     * Map's a policy's identifier to the policies for deployment.
+     */
+    private Map<ToscaConceptIdentifier, ToscaPolicy> policiesToBeDeployed = new HashMap<>();
+
+    /**
+     * Set of policies to be undeployed.
+     */
+    private Set<ToscaConceptIdentifier> policiesToBeUndeployed = new HashSet<>();
+
+    /**
      * Tracks policy deployment status so notifications can be generated.
      */
     private final DeploymentStatus deployStatus;
@@ -358,6 +371,24 @@
     }
 
     /**
+     * Gets the list of policies to be deployed to the PDPs.
+     *
+     * @returns a list of policies to be deployed
+     */
+    public List<ToscaPolicy> getPoliciesToBeDeployed() {
+        return new LinkedList<>(this.policiesToBeDeployed.values());
+    }
+
+    /**
+     * Gets the list of policies to be undeployed from the PDPs.
+     *
+     * @returns a list of policies to be undeployed
+     */
+    public List<ToscaConceptIdentifier> getPoliciesToBeUndeployed() {
+        return new LinkedList<>(this.policiesToBeUndeployed);
+    }
+
+    /**
      * Adds a group to the group cache, if it isn't already in the cache.
      *
      * @param group the group to be added
@@ -422,14 +453,17 @@
     /**
      * Adds policy deployment data.
      *
-     * @param policyId ID of the policy being deployed
+     * @param policy policy being deployed
      * @param pdps PDPs to which the policy is being deployed
      * @param pdpGroup PdpGroup containing the PDP of interest
      * @param pdpType PDP type (i.e., PdpSubGroup) containing the PDP of interest
      * @throws PfModelException if an error occurred
      */
-    protected void trackDeploy(ToscaConceptIdentifier policyId, Collection<String> pdps, String pdpGroup,
+    protected void trackDeploy(ToscaPolicy policy, Collection<String> pdps, String pdpGroup,
             String pdpType) throws PfModelException {
+        ToscaConceptIdentifier policyId = policy.getIdentifier();
+        policiesToBeDeployed.put(policyId, policy);
+        
         addData(policyId, pdps, pdpGroup, pdpType, true);
     }
 
@@ -444,6 +478,7 @@
      */
     protected void trackUndeploy(ToscaConceptIdentifier policyId, Collection<String> pdps, String pdpGroup,
             String pdpType) throws PfModelException {
+        policiesToBeUndeployed.add(policyId);
         addData(policyId, pdps, pdpGroup, pdpType, false);
     }
 
diff --git a/main/src/test/java/org/onap/policy/pap/main/comm/PdpHeartbeatListenerTest.java b/main/src/test/java/org/onap/policy/pap/main/comm/PdpHeartbeatListenerTest.java
index 01edbdc..d2dc195 100644
--- a/main/src/test/java/org/onap/policy/pap/main/comm/PdpHeartbeatListenerTest.java
+++ b/main/src/test/java/org/onap/policy/pap/main/comm/PdpHeartbeatListenerTest.java
@@ -21,14 +21,18 @@
 
 package org.onap.policy.pap.main.comm;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
 
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.time.Instant;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
+import java.util.stream.Collectors;
 import org.junit.Test;
 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
 import org.onap.policy.common.utils.coder.CoderException;
@@ -37,9 +41,12 @@
 import org.onap.policy.models.pdp.concepts.PdpStatistics;
 import org.onap.policy.models.pdp.concepts.PdpStatus;
 import org.onap.policy.models.pdp.concepts.PdpSubGroup;
+import org.onap.policy.models.pdp.concepts.PdpUpdate;
 import org.onap.policy.models.pdp.enums.PdpHealthStatus;
 import org.onap.policy.models.pdp.enums.PdpState;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
+import org.onap.policy.pap.main.parameters.CommonTestData;
 import org.onap.policy.pap.main.parameters.PdpParameters;
 import org.onap.policy.pap.main.rest.e2e.End2EndBase;
 
@@ -202,6 +209,29 @@
         status9.setPolicies(idents9);
         pdpHeartbeatListener.onTopicEvent(INFRA, TOPIC, status9);
         verifyPdpGroup(DEFAULT_GROUP, 0);
+
+        // Test policy lists updated in createUpdate
+        ToscaPolicy polA = new ToscaPolicy();
+        polA.setName("pol-a-1.1.1");
+        polA.setVersion("1.1.1");
+        ToscaPolicy polB = new ToscaPolicy();
+        polB.setName("pol-b-1.1.1");
+        polB.setVersion("1.1.1");
+        List<ToscaPolicy> policies = new ArrayList<>();
+        policies.add(polA);
+        policies.add(polB);
+        final CommonTestData testData = new CommonTestData();
+        PdpParameters params = testData.getPapParameterGroup(1).getPdpParameters();
+        List<ToscaConceptIdentifier> polsUndep = policies.stream().map(ToscaPolicy::getIdentifier)
+                .collect(Collectors.toList());
+        PdpStatusMessageHandler handler = new PdpStatusMessageHandler(params);
+        PdpUpdate update10 = handler.createPdpUpdateMessage(
+                status3.getPdpGroup(), new PdpSubGroup(), "pdp_2",
+                null, policies, policies, polsUndep);
+        assertSame(update10.getPolicies(), policies);
+        assertSame(update10.getPoliciesToBeDeployed(), policies);
+        assertSame(update10.getPoliciesToBeUndeployed(), polsUndep);
+        assertThat(update10.getPoliciesToBeDeployed()).isInstanceOf(List.class);
     }
 
     @Test
diff --git a/main/src/test/java/org/onap/policy/pap/main/comm/msgdata/UpdateReqTest.java b/main/src/test/java/org/onap/policy/pap/main/comm/msgdata/UpdateReqTest.java
index ca6a62c..d85bf73 100644
--- a/main/src/test/java/org/onap/policy/pap/main/comm/msgdata/UpdateReqTest.java
+++ b/main/src/test/java/org/onap/policy/pap/main/comm/msgdata/UpdateReqTest.java
@@ -20,8 +20,10 @@
 
 package org.onap.policy.pap.main.comm.msgdata;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
@@ -32,6 +34,8 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.stream.Collectors;
@@ -40,6 +44,7 @@
 import org.onap.policy.models.pdp.concepts.PdpStateChange;
 import org.onap.policy.models.pdp.concepts.PdpStatus;
 import org.onap.policy.models.pdp.concepts.PdpUpdate;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
 import org.onap.policy.pap.main.comm.CommonRequestBase;
 
@@ -185,7 +190,7 @@
         // same content - should succeed, but leave message unchanged
         PdpUpdate msg2 = new PdpUpdate(update);
         assertTrue(data.reconfigure(msg2));
-        assertSame(update, data.getMessage());
+        assertNotSame(update, data.getMessage());
 
         // different content - should succeed and install NEW message
         msg2.setPdpGroup(DIFFERENT);
@@ -194,15 +199,106 @@
     }
 
     @Test
+    public void testReconfigureIsFullSameAsDeployList() {
+        PdpUpdate msg2 = new PdpUpdate(update);
+        ArrayList<ToscaPolicy> policies = new ArrayList<>(update.getPolicies());
+
+        msg2.setPolicies(policies);
+        msg2.setPoliciesToBeDeployed(policies);
+        assertTrue(data.reconfigure(msg2));
+        assertThat(data.getMessage().getPolicies()).containsAll(msg2.getPolicies());
+    }
+
+    @Test
+    public void testListsNewVsResult() {
+        PdpUpdate msg2 = new PdpUpdate(update);
+        ArrayList<ToscaPolicy> policies = new ArrayList<>(update.getPolicies());
+
+        // some items in both deploy and newMessage.deploy
+        msg2.setPoliciesToBeDeployed(policies);
+        policies.remove(0);
+        data.getMessage().setPolicies(policies);
+        assertTrue(data.reconfigure(msg2));
+        assertThat(data.getMessage().getPoliciesToBeDeployed()).containsAll(msg2.getPoliciesToBeDeployed());
+
+        // some items in both deploy and newMessage.undeploy
+        policies = new ArrayList<>();
+        policies.add(makePolicy("policy-z-1", "1.0.0"));
+        policies.add(makePolicy("policy-y-1", "1.0.0"));
+        data.getMessage().setPoliciesToBeDeployed(policies);
+
+        policies.clear();
+        policies = new ArrayList<>(update.getPolicies());
+        List<ToscaConceptIdentifier> polsToUndep = policies.parallelStream()
+                .map(ToscaPolicy::getIdentifier)
+                .collect(Collectors.toList());
+        msg2.setPoliciesToBeUndeployed(polsToUndep);
+
+        assertTrue(data.reconfigure(msg2));
+
+        List<ToscaConceptIdentifier> dataPols = data.getMessage().getPoliciesToBeDeployed().stream()
+                .map(ToscaPolicy::getIdentifier)
+                .collect(Collectors.toList());
+        assertThat(dataPols).doesNotContainAnyElementsOf(data.getMessage().getPoliciesToBeUndeployed());
+
+        // some items only in deploy
+        policies = new ArrayList<>(update.getPolicies());
+        msg2.setPoliciesToBeDeployed(policies);
+        data.getMessage().setPoliciesToBeDeployed(new LinkedList<>());
+        assertTrue(data.reconfigure(msg2));
+        assertThat(data.getMessage().getPoliciesToBeDeployed()).containsAll(msg2.getPoliciesToBeDeployed());
+
+        // some items in both undeploy and newMessage.undeploy
+        List<ToscaConceptIdentifier> pols = policies.stream().map(ToscaPolicy::getIdentifier)
+                .collect(Collectors.toList());
+        msg2.setPoliciesToBeUndeployed(pols);
+        pols.remove(0);
+        data.getMessage().setPoliciesToBeUndeployed(pols);
+        assertTrue(data.reconfigure(msg2));
+        assertThat(data.getMessage().getPoliciesToBeUndeployed()).containsAll(msg2.getPoliciesToBeUndeployed());
+
+        // some items in both undeploy and newMessage.deploy
+        policies = new ArrayList<>(update.getPolicies());
+        List<ToscaConceptIdentifier> polsToUndep2 = policies.parallelStream()
+                .map(ToscaPolicy::getIdentifier)
+                .collect(Collectors.toList());
+        data.getMessage().setPoliciesToBeUndeployed(polsToUndep2);
+
+        List<ToscaPolicy> polsToDep2 = new LinkedList<>();
+        polsToDep2.add(makePolicy("policy-m-1", "1.0.0"));
+        polsToDep2.add(makePolicy("policy-n-1", "1.0.0"));
+        msg2.setPoliciesToBeDeployed(polsToDep2);
+
+        assertTrue(data.reconfigure(msg2));
+
+        List<ToscaConceptIdentifier> dataPols2 = data.getMessage().getPoliciesToBeDeployed().stream()
+                .map(ToscaPolicy::getIdentifier)
+                .collect(Collectors.toList());
+        assertThat(data.getMessage().getPoliciesToBeUndeployed())
+                .doesNotContainAnyElementsOf(dataPols2);
+
+        // some items only in undeploy
+        pols = policies.stream().map(ToscaPolicy::getIdentifier)
+                .collect(Collectors.toList());
+        msg2.setPoliciesToBeUndeployed(pols);
+        data.getMessage().setPoliciesToBeUndeployed(new LinkedList<>());
+        assertTrue(data.reconfigure(msg2));
+        assertThat(data.getMessage().getPoliciesToBeUndeployed()).containsAll(msg2.getPoliciesToBeUndeployed());
+    }
+
+    @Test
     public void testIsSameContent() {
+        data = new UpdateReq(reqParams, MY_REQ_NAME, update);
+        data.setNotifier(notifier);
+
         PdpUpdate msg2 = new PdpUpdate(update);
         msg2.setName("world");
-        assertTrue(data.isSameContent(msg2));
+        assertFalse(data.isSameContent(msg2));
 
         // both policy lists null
         update.setPolicies(null);
         msg2.setPolicies(null);
-        assertTrue(data.isSameContent(msg2));
+        assertEquals(data.getMessage().getPolicies(), msg2.getPolicies());
     }
 
     @Test
@@ -210,7 +306,7 @@
         PdpUpdate msg2 = new PdpUpdate(update);
         msg2.setPdpGroup(null);
         update.setPdpGroup(null);
-        assertTrue(data.isSameContent(msg2));
+        assertEquals(data.getMessage().getPdpGroup(), msg2.getPdpGroup());
     }
 
     @Test
@@ -218,7 +314,7 @@
         PdpUpdate msg2 = new PdpUpdate(update);
         msg2.setPdpSubgroup(null);
         update.setPdpSubgroup(null);
-        assertTrue(data.isSameContent(msg2));
+        assertEquals(data.getMessage().getPdpSubgroup(), msg2.getPdpSubgroup());
     }
 
     @Test
diff --git a/main/src/test/java/org/onap/policy/pap/main/rest/TestProviderBase.java b/main/src/test/java/org/onap/policy/pap/main/rest/TestProviderBase.java
index b2c67c9..2bf4f3d 100644
--- a/main/src/test/java/org/onap/policy/pap/main/rest/TestProviderBase.java
+++ b/main/src/test/java/org/onap/policy/pap/main/rest/TestProviderBase.java
@@ -361,11 +361,13 @@
                     // queue indicated that the update should succeed
                     subgroup.getPolicies().add(ident1);
 
-                    data.trackDeploy(ident1, Collections.singleton(PDP1), GROUP1_NAME, PDP1_TYPE);
+                    ToscaPolicy testPolicy1 = data.getPolicy(new ToscaConceptIdentifierOptVersion(ident1));
+                    data.trackDeploy(testPolicy1, Collections.singleton(PDP1), GROUP1_NAME, PDP1_TYPE);
                     data.trackUndeploy(ident1, Collections.singleton(PDP2), GROUP1_NAME, PDP2_TYPE);
 
                     ToscaConceptIdentifier ident2 = new ToscaConceptIdentifier(POLICY1_NAME, "9.9.9");
-                    data.trackDeploy(ident2, Collections.singleton(PDP3), GROUP1_NAME, PDP3_TYPE);
+                    ToscaPolicy testPolicy2 = data.getPolicy(new ToscaConceptIdentifierOptVersion(ident2));
+                    data.trackDeploy(testPolicy2, Collections.singleton(PDP3), GROUP1_NAME, PDP3_TYPE);
                     data.trackUndeploy(ident2, Collections.singleton(PDP4), GROUP1_NAME, PDP4_TYPE);
                     return true;
 
diff --git a/main/src/test/java/org/onap/policy/pap/main/rest/TestSessionData.java b/main/src/test/java/org/onap/policy/pap/main/rest/TestSessionData.java
index 6b76c25..ad24916 100644
--- a/main/src/test/java/org/onap/policy/pap/main/rest/TestSessionData.java
+++ b/main/src/test/java/org/onap/policy/pap/main/rest/TestSessionData.java
@@ -577,15 +577,19 @@
         ToscaConceptIdentifier policyId = new ToscaConceptIdentifier(POLICY_NAME, POLICY_VERSION);
         List<String> pdps = Arrays.asList(PDP1, PDP2);
 
+        ToscaPolicy testPolicy = session.getPolicy(new ToscaConceptIdentifierOptVersion(policyId));
+
         if (deploy) {
-            session.trackDeploy(policyId, pdps, GROUP_NAME, PDP_TYPE);
+            session.trackDeploy(testPolicy, pdps, GROUP_NAME, PDP_TYPE);
+            assertThat(session.getPoliciesToBeDeployed()).contains(testPolicy);
         } else {
             session.trackUndeploy(policyId, pdps, GROUP_NAME, PDP_TYPE);
+            assertThat(session.getPoliciesToBeUndeployed()).contains(policyId);
         }
 
         // should be called just once
         verify(status).deleteDeployment(any(), anyBoolean());
-        verify(status).deleteDeployment(policyId, !deploy);
+        verify(status, times(1)).deleteDeployment(policyId, !deploy);
 
         // should be called for each PDP
         verify(status, times(2)).deploy(any(), any(), any(), any(), any(), anyBoolean());