Rework the backend to support PDP updates

Add new mem structure so that we do not need to parse the same Json for each policy/type + rework the camel flows so that we use the same code for loop and policies related calls

Issue-ID: POLICY-2930
Issue-ID: POLICY-2931
Signed-off-by: sebdet <sebastien.determe@intl.att.com>
Change-Id: I3c30c4f87cf669b40511472d518fe5ccc89f56f0
diff --git a/src/main/java/org/onap/policy/clamp/loop/components/external/PolicyComponent.java b/src/main/java/org/onap/policy/clamp/loop/components/external/PolicyComponent.java
index 648463d..ff4e264 100644
--- a/src/main/java/org/onap/policy/clamp/loop/components/external/PolicyComponent.java
+++ b/src/main/java/org/onap/policy/clamp/loop/components/external/PolicyComponent.java
@@ -1,8 +1,8 @@
 /*-
  * ============LICENSE_START=======================================================
- * ONAP CLAMP
+ * ONAP POLICY-CLAMP
  * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
  *                             reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,20 +25,19 @@
 
 import com.att.eelf.configuration.EELFLogger;
 import com.att.eelf.configuration.EELFManager;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonObject;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
 import javax.persistence.Transient;
 import org.apache.camel.Exchange;
+import org.onap.policy.clamp.clds.util.JsonUtils;
 import org.onap.policy.clamp.loop.Loop;
 import org.onap.policy.clamp.policy.microservice.MicroServicePolicy;
 import org.onap.policy.clamp.policy.operational.OperationalPolicy;
+import org.onap.policy.clamp.policy.pdpgroup.PdpGroupPayload;
 
+/**
+ * This class represents the policy state according to all policies involved in the control loop.
+ * It can compute it with all policy queries result.
+ * It contains also the method to generate the PDP payload used for the policies deployment.
+ */
 public class PolicyComponent extends ExternalComponent {
 
     @Transient
@@ -81,81 +80,22 @@
      * @return The json, payload to send
      */
     public static String createPoliciesPayloadPdpGroup(Loop loop, String action) {
-        Map<String, Map<String, List<JsonObject>>> pdpGroupMap = new HashMap<>();
+        PdpGroupPayload pdpGroupPayload = new PdpGroupPayload();
         for (OperationalPolicy opPolicy : loop.getOperationalPolicies()) {
-            updatePdpGroupMap(opPolicy.getPdpGroup(), opPolicy.getPdpSubgroup(),
-                    opPolicy.getName(),
-                    "1.0.0", pdpGroupMap);
+            pdpGroupPayload
+                    .updatePdpGroupMap(opPolicy.getPdpGroup(), opPolicy.getPdpSubgroup(), opPolicy.getName(), "1.0.0");
         }
 
         for (MicroServicePolicy msPolicy : loop.getMicroServicePolicies()) {
-            updatePdpGroupMap(msPolicy.getPdpGroup(), msPolicy.getPdpSubgroup(),
-                    msPolicy.getName(),
-                    "1.0.0", pdpGroupMap);
+            pdpGroupPayload
+                    .updatePdpGroupMap(msPolicy.getPdpGroup(), msPolicy.getPdpSubgroup(), msPolicy.getName(), "1.0.0");
         }
 
-        String payload = new GsonBuilder().setPrettyPrinting().create()
-                .toJson(generateActivatePdpGroupPayload(pdpGroupMap, action));
+        String payload = JsonUtils.GSON.toJson(pdpGroupPayload.generateActivatePdpGroupPayload(action));
         logger.info("PdpGroup policy payload: " + payload);
         return payload;
     }
 
-    private static void updatePdpGroupMap(String pdpGroup,
-                                          String pdpSubGroup,
-                                          String policyName,
-                                          String policyVersion,
-                                          Map<String, Map<String,
-                                                  List<JsonObject>>> pdpGroupMap) {
-        JsonObject policyJson = new JsonObject();
-        policyJson.addProperty("name", policyName);
-        policyJson.addProperty("version", policyVersion);
-        Map<String, List<JsonObject>> pdpSubGroupMap;
-        List<JsonObject> policyList;
-        if (pdpGroupMap.get(pdpGroup) == null) {
-            pdpSubGroupMap = new HashMap<>();
-            policyList = new LinkedList<>();
-        } else {
-            pdpSubGroupMap = pdpGroupMap.get(pdpGroup);
-            if (pdpSubGroupMap.get(pdpSubGroup) == null) {
-                policyList = new LinkedList<>();
-            } else {
-                policyList = (List<JsonObject>) pdpSubGroupMap.get(pdpSubGroup);
-            }
-        }
-        policyList.add(policyJson);
-        pdpSubGroupMap.put(pdpSubGroup, policyList);
-        pdpGroupMap.put(pdpGroup, pdpSubGroupMap);
-    }
-
-    private static JsonObject generateActivatePdpGroupPayload(
-            Map<String, Map<String, List<JsonObject>>> pdpGroupMap, String action) {
-        JsonArray payloadArray = new JsonArray();
-        for (Entry<String, Map<String, List<JsonObject>>> pdpGroupInfo : pdpGroupMap.entrySet()) {
-            JsonObject pdpGroupNode = new JsonObject();
-            JsonArray subPdpArray = new JsonArray();
-            pdpGroupNode.addProperty("name", pdpGroupInfo.getKey());
-            pdpGroupNode.add("deploymentSubgroups", subPdpArray);
-
-            for (Entry<String, List<JsonObject>> pdpSubGroupInfo : pdpGroupInfo.getValue().entrySet()) {
-                JsonObject pdpSubGroupNode = new JsonObject();
-                subPdpArray.add(pdpSubGroupNode);
-                pdpSubGroupNode.addProperty("pdpType", pdpSubGroupInfo.getKey());
-                pdpSubGroupNode.addProperty("action", action);
-
-                JsonArray policyArray = new JsonArray();
-                pdpSubGroupNode.add("policies", policyArray);
-
-                for (JsonObject policy : pdpSubGroupInfo.getValue()) {
-                    policyArray.add(policy);
-                }
-            }
-            payloadArray.add(pdpGroupNode);
-        }
-        JsonObject jsonObject = new JsonObject();
-        jsonObject.add("groups", payloadArray);
-        return jsonObject;
-    }
-
     private static ExternalComponentState findNewState(boolean found, boolean deployed) {
 
         ExternalComponentState newState = NOT_SENT;
diff --git a/src/main/java/org/onap/policy/clamp/loop/deploy/DcaeDeployParameters.java b/src/main/java/org/onap/policy/clamp/loop/deploy/DcaeDeployParameters.java
index 9d56f23..1a14146 100644
--- a/src/main/java/org/onap/policy/clamp/loop/deploy/DcaeDeployParameters.java
+++ b/src/main/java/org/onap/policy/clamp/loop/deploy/DcaeDeployParameters.java
@@ -1,8 +1,8 @@
 /*-
  * ============LICENSE_START=======================================================
- * ONAP CLAMP
+ * ONAP POLICY-CLAMP
  * ================================================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
  *                             reserved.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -109,5 +109,4 @@
         globalProperties.add("dcaeDeployParameters", deployParamJson);
         return globalProperties;
     }
-
 }
diff --git a/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayload.java b/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayload.java
new file mode 100644
index 0000000..c893950
--- /dev/null
+++ b/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayload.java
@@ -0,0 +1,108 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights
+ *                             reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.pdpgroup;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This is an utility class that build the PDP group policy payload.
+ * This is used when policies have to be deployed to PDP group/subgroups on the Policy Engine.
+ */
+public class PdpGroupPayload {
+
+    private Map<String, Map<String, List<JsonObject>>> pdpGroupMap = new HashMap<>();
+
+    /**
+     * This method updates the pdpGroupMap structure for a specific policy/version/pdpdGroup/PdpSubGroup.
+     *
+     * @param pdpGroup The pdp Group in String
+     * @param pdpSubGroup The pdp Sub Group in String
+     * @param policyName The policy name
+     * @param policyVersion The policy Version
+     */
+    public void updatePdpGroupMap(String pdpGroup,
+                                          String pdpSubGroup,
+                                          String policyName,
+                                          String policyVersion) {
+        JsonObject policyJson = new JsonObject();
+        policyJson.addProperty("name", policyName);
+        policyJson.addProperty("version", policyVersion);
+        Map<String, List<JsonObject>> pdpSubGroupMap;
+        List<JsonObject> policyList;
+        if (pdpGroupMap.get(pdpGroup) == null) {
+            pdpSubGroupMap = new HashMap<>();
+            policyList = new LinkedList<>();
+        } else {
+            pdpSubGroupMap = pdpGroupMap.get(pdpGroup);
+            if (pdpSubGroupMap.get(pdpSubGroup) == null) {
+                policyList = new LinkedList<>();
+            } else {
+                policyList = pdpSubGroupMap.get(pdpSubGroup);
+            }
+        }
+        policyList.add(policyJson);
+        pdpSubGroupMap.put(pdpSubGroup, policyList);
+        pdpGroupMap.put(pdpGroup, pdpSubGroupMap);
+    }
+
+    /**
+     * This method generates the Payload in Json from the pdp Group structure containing the policies/versions
+     * that must be sent to the policy framework.
+     *
+     * @param action The action to do, either a POST or a DELETE
+     * @return The Json that can be sent to policy framework as JsonObject
+     */
+    public JsonObject generateActivatePdpGroupPayload(String action) {
+        JsonArray payloadArray = new JsonArray();
+        for (Map.Entry<String, Map<String, List<JsonObject>>> pdpGroupInfo : pdpGroupMap.entrySet()) {
+            JsonObject pdpGroupNode = new JsonObject();
+            JsonArray subPdpArray = new JsonArray();
+            pdpGroupNode.addProperty("name", pdpGroupInfo.getKey());
+            pdpGroupNode.add("deploymentSubgroups", subPdpArray);
+
+            for (Map.Entry<String, List<JsonObject>> pdpSubGroupInfo : pdpGroupInfo.getValue().entrySet()) {
+                JsonObject pdpSubGroupNode = new JsonObject();
+                subPdpArray.add(pdpSubGroupNode);
+                pdpSubGroupNode.addProperty("pdpType", pdpSubGroupInfo.getKey());
+                pdpSubGroupNode.addProperty("action", action);
+
+                JsonArray policyArray = new JsonArray();
+                pdpSubGroupNode.add("policies", policyArray);
+
+                for (JsonObject policy : pdpSubGroupInfo.getValue()) {
+                    policyArray.add(policy);
+                }
+            }
+            payloadArray.add(pdpGroupNode);
+        }
+        JsonObject jsonObject = new JsonObject();
+        jsonObject.add("groups", payloadArray);
+        return jsonObject;
+    }
+}
diff --git a/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupsAnalyzer.java b/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupsAnalyzer.java
index 7688727..6098d0f 100644
--- a/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupsAnalyzer.java
+++ b/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupsAnalyzer.java
@@ -25,9 +25,14 @@
 
 import com.google.gson.JsonArray;
 import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
-import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.commons.collections4.CollectionUtils;
+import org.onap.policy.clamp.clds.util.JsonUtils;
 import org.onap.policy.clamp.loop.template.PolicyModel;
 import org.onap.policy.models.pdp.concepts.PdpGroup;
 import org.onap.policy.models.pdp.concepts.PdpGroups;
@@ -44,8 +49,77 @@
     public static final String SUPPORTED_PDP_GROUPS_INFO = "supportedPdpGroups";
 
     /**
-     * Get supported subGroups based on the defined policy type and version for s specific PDPgroup.
-     * It returns null if the Group is not ACTIVE or if the policytype/version has not been found in the PDPSubgroups.
+     * This structure holds the map of PdpGroups per policies, policies are identifed by ToscaConceptIdentifier.
+     */
+    private final Map<ToscaConceptIdentifier, Map<String, PdpGroup>> pdpGroupsDeploymentPerPolicy =
+            new ConcurrentHashMap<>();
+
+    /**
+     * Constructor taking he PDPGroups info from the PEF.
+     * It then caches the groups per policies and per types.
+     *
+     * @param pdpGroups The pdpgroup info from the PEF
+     */
+    public PdpGroupsAnalyzer(PdpGroups pdpGroups) {
+        this.analyzePdpGroups(pdpGroups);
+    }
+
+    /**
+     * Getter of the GroupDeploymentPerPolicy structure.
+     *
+     * @return The map of policies.
+     */
+    public Map<ToscaConceptIdentifier, Map<String, PdpGroup>> getPdpGroupsDeploymentPerPolicy() {
+        return pdpGroupsDeploymentPerPolicy;
+    }
+
+    private static void addInfoToPdpGroupsStructure(ToscaConceptIdentifier toscaId,
+                                                    Map<ToscaConceptIdentifier,
+                                                            Map<String,
+                                                                    PdpGroup>> pdpGroupsDeploymentPerToscaIdentifier,
+                                                    PdpGroup pdpGroupSource,
+                                                    PdpSubGroup pdpSubGroupSource) {
+        // Copy the subgroup but empty the policies & types
+        pdpGroupsDeploymentPerToscaIdentifier.computeIfAbsent(toscaId, toscaKey -> new ConcurrentHashMap<>())
+                .computeIfAbsent(pdpGroupSource.getName(), pdpGroupName -> {
+                    PdpGroup pdpGroupCopy = new PdpGroup(pdpGroupSource);
+                    pdpGroupCopy.setPdpSubgroups(new ArrayList<>());
+                    return pdpGroupCopy;
+                }).getPdpSubgroups().add(new PdpSubGroup(pdpSubGroupSource));
+    }
+
+    private void analyzePdpGroups(PdpGroups pdpGroups) {
+        CollectionUtils.emptyIfNull(pdpGroups.getGroups()).stream()
+                .forEach(group -> CollectionUtils.emptyIfNull(group.getPdpSubgroups()).stream().forEach(subGroup ->
+                        CollectionUtils.emptyIfNull(subGroup.getPolicies()).parallelStream().forEach(policy ->
+                                PdpGroupsAnalyzer.addInfoToPdpGroupsStructure(policy, this.pdpGroupsDeploymentPerPolicy,
+                                        group, subGroup))));
+    }
+
+    /**
+     * This method retrieves all pdpGroups and subgroups where a specific policy name/version is deployed.
+     *
+     * @param policyName The policy name that must be used for searching
+     * @param version    THe policy version that must be used for searching
+     * @return It returns a JsonObject containing each pdpGroup and subgroups associated
+     */
+    public JsonObject getPdpGroupsForPolicy(String policyName, String version) {
+        Map<String, PdpGroup> mapOfGroups =
+                this.pdpGroupsDeploymentPerPolicy.get(new ToscaConceptIdentifier(policyName, version));
+        if (mapOfGroups != null) {
+            JsonObject policyPdpGroups = new JsonObject();
+            JsonArray pdpGroupsArray = new JsonArray();
+            policyPdpGroups.add(ASSIGNED_PDP_GROUPS_INFO, pdpGroupsArray);
+            pdpGroupsArray.add(JsonUtils.GSON
+                    .toJsonTree(mapOfGroups));
+            return policyPdpGroups;
+        }
+        return null;
+    }
+
+    /**
+     * Get supported subGroups based on the defined policy type and version for specific PDPGroup.
+     * It returns null if the Group is TERMINATED or if the policytype/version has not been found in the PDPSubgroups.
      *
      * @param pdpGroup   The pdpGroup that must be analyzed
      * @param policyType The policy type
@@ -56,7 +130,7 @@
      */
     private static JsonObject getSupportedPdpSubgroupsForModelType(PdpGroup pdpGroup, String policyType,
                                                                    String version) {
-        if (!PdpState.ACTIVE.equals(pdpGroup.getPdpGroupState())) {
+        if (PdpState.TERMINATED.equals(pdpGroup.getPdpGroupState())) {
             return null;
         }
         JsonObject supportedPdpGroup = new JsonObject();
@@ -87,7 +161,7 @@
 
         pdpGroups.getGroups().stream().map(pdpGroup -> PdpGroupsAnalyzer.getSupportedPdpSubgroupsForModelType(pdpGroup,
                 policyType, version)).filter(Objects::nonNull)
-                .forEach(jsonPdpGroup -> pdpGroupsArray.add(jsonPdpGroup));
+                .forEach(pdpGroupsArray::add);
 
         return pdpGroupsArray.size() != 0 ? supportedPdpGroups : null;
     }
@@ -99,38 +173,8 @@
      * @param pdpGroups        The PdpGroups containing all PDP group definition
      */
     public static void updatePdpGroupOfPolicyModels(List<PolicyModel> policyModelsList, PdpGroups pdpGroups) {
-        policyModelsList.parallelStream().forEach(policyModel -> {
-            policyModel.setPolicyPdpGroup(getSupportedPdpGroupsForModelType(pdpGroups, policyModel.getPolicyModelType(),
-                    policyModel.getVersion()));
-        });
-    }
-
-    /**
-     * This method searches for the PdpGroup/subgroup where the policy given is currently deployed.
-     *
-     * @param pdpGroups The pdpGroups info from PEF
-     * @param policyName The policy Id
-     * @param version The policy version
-     * @return It returns a JsonObject containing the pdpGroup/subgroup info
-     */
-    public static JsonObject getPdpGroupDeploymentOfOnePolicy(PdpGroups pdpGroups, String policyName, String version) {
-        JsonObject pdpGroupInfo = new JsonObject();
-        JsonObject assignedPdpGroups = new JsonObject();
-        pdpGroupInfo.add(ASSIGNED_PDP_GROUPS_INFO, assignedPdpGroups);
-
-        ToscaConceptIdentifier toscaConceptIdentifier = new ToscaConceptIdentifier(policyName, version);
-        pdpGroups.getGroups().stream().anyMatch(pdpGroup ->
-                pdpGroup.getPdpSubgroups().stream().anyMatch(
-                        pdpSubGroup -> {
-                            if (pdpSubGroup.getPolicies() != null && pdpSubGroup.getPolicies()
-                                    .contains(toscaConceptIdentifier)) {
-                                assignedPdpGroups.addProperty("pdpGroup", pdpGroup.getName());
-                                assignedPdpGroups.addProperty("pdpSubGroup", pdpSubGroup.getPdpType());
-                                return true;
-                            }
-                            return false;
-                        })
-        );
-        return assignedPdpGroups.entrySet().isEmpty() ? null : pdpGroupInfo;
+        policyModelsList.parallelStream().forEach(policyModel -> policyModel
+                .setPolicyPdpGroup(getSupportedPdpGroupsForModelType(pdpGroups, policyModel.getPolicyModelType(),
+                        policyModel.getVersion())));
     }
 }
\ No newline at end of file
diff --git a/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMerger.java b/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMerger.java
index 44b1111..6775eb0 100644
--- a/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMerger.java
+++ b/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMerger.java
@@ -23,11 +23,8 @@
 
 package org.onap.policy.clamp.policy.pdpgroup;
 
-import com.google.gson.Gson;
-import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
-import java.util.Map;
 import java.util.stream.StreamSupport;
 import org.onap.policy.clamp.clds.util.JsonUtils;
 import org.onap.policy.models.pdp.concepts.PdpGroups;
@@ -38,6 +35,8 @@
  */
 public class PoliciesPdpMerger {
 
+    private PoliciesPdpMerger() {}
+
     /**
      * This method extract the content of a policy without knowing the key (policy Id).
      * This JsonElement normally contains only the policy ID then the content,
@@ -91,8 +90,9 @@
      * @param policyJsonNode The policy json node that must be enriched
      */
     private static void enrichOnePolicy(PdpGroups pdpGroups, JsonObject policyJsonNode) {
-        JsonObject deploymentPdpJson = PdpGroupsAnalyzer
-                .getPdpGroupDeploymentOfOnePolicy(pdpGroups, policyJsonNode.get("name").getAsString(),
+        PdpGroupsAnalyzer pdpGroupAnalyzer = new PdpGroupsAnalyzer(pdpGroups);
+        JsonObject deploymentPdpJson = pdpGroupAnalyzer
+                .getPdpGroupsForPolicy(policyJsonNode.get("name").getAsString(),
                         policyJsonNode.get("version").getAsString());
         mergeJsonElement(policyJsonNode, deploymentPdpJson);
 
@@ -101,18 +101,4 @@
                         policyJsonNode.get("type_version").getAsString());
         mergeJsonElement(policyJsonNode, supportedPdpGroupsJson);
     }
-
-    /**
-     * This method removes the pdp States added for one policy.
-     *
-     * @param policyJsonNode The policy node Json as String
-     * @return The Json with pdp group info removed
-     */
-    public static JsonObject removePdpStatesOnePolicy(JsonObject policyJsonNode) {
-        //JsonObject policyJson = JsonUtils.GSON.fromJson(policyJsonNode, JsonObject.class);
-        // Simply remove the nodes we have added.
-        policyJsonNode.remove(PdpGroupsAnalyzer.ASSIGNED_PDP_GROUPS_INFO);
-        policyJsonNode.remove(PdpGroupsAnalyzer.SUPPORTED_PDP_GROUPS_INFO);
-        return policyJsonNode;
-    }
 }
\ No newline at end of file
diff --git a/src/main/resources/clds/camel/rest/clamp-api-v2.xml b/src/main/resources/clds/camel/rest/clamp-api-v2.xml
index 7de2de1..de0bb1a 100644
--- a/src/main/resources/clds/camel/rest/clamp-api-v2.xml
+++ b/src/main/resources/clds/camel/rest/clamp-api-v2.xml
@@ -437,7 +437,7 @@
                     <to
                             uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('RESTART request','INFO',${exchangeProperty[loopObject]})"/>
 
-                    <to uri="direct:add-all-to-active-pdp-group"/>
+                    <to uri="direct:add-policies-from-loop-to-pdp-group"/>
                     <log loggingLevel="INFO"
                          message="RESTART request successfully executed for loop: ${header.loopName}"/>
                     <to
@@ -524,7 +524,7 @@
                         <constant>3000</constant>
                     </delay>
 
-                    <to uri="direct:add-all-to-active-pdp-group"/>
+                    <to uri="direct:add-policies-from-loop-to-pdp-group"/>
 
                     <log loggingLevel="INFO"
                          message="SUBMIT request successfully executed for loop: ${header.loopName}"/>
diff --git a/src/main/resources/clds/camel/routes/policy-flows.xml b/src/main/resources/clds/camel/routes/policy-flows.xml
index c926178..cc51a08 100644
--- a/src/main/resources/clds/camel/routes/policy-flows.xml
+++ b/src/main/resources/clds/camel/routes/policy-flows.xml
@@ -208,8 +208,8 @@
         </doTry>
     </route>
 
-    <route id="add-all-to-active-pdp-group">
-        <from uri="direct:add-all-to-active-pdp-group"/>
+    <route id="add-policies-from-loop-to-pdp-group">
+        <from uri="direct:add-policies-from-loop-to-pdp-group"/>
         <doTry>
             <log loggingLevel="INFO"
                  message="Adding loop policies to PDP Group: ${exchangeProperty[loopObject].getName()}"/>
@@ -220,31 +220,8 @@
                     ${exchangeProperty[loopObject].getComponent("POLICY").createPoliciesPayloadPdpGroup(exchangeProperty[loopObject],"POST")}
                 </simple>
             </setBody>
-            <setHeader headerName="CamelHttpMethod">
-                <constant>POST</constant>
-            </setHeader>
-            <setHeader headerName="Content-Type">
-                <constant>application/json</constant>
-            </setHeader>
-            <setHeader headerName="X-ONAP-RequestID">
-                <simple>${exchangeProperty[X-ONAP-RequestID]}
-                </simple>
-            </setHeader>
-            <setHeader headerName="X-ONAP-InvocationID">
-                <simple>${exchangeProperty[X-ONAP-InvocationID]}
-                </simple>
-            </setHeader>
-            <setHeader headerName="X-ONAP-PartnerName">
-                <simple>${exchangeProperty[X-ONAP-PartnerName]}
-                </simple>
-            </setHeader>
-            <log loggingLevel="INFO"
-                 message="Endpoint to add policies to PDP Group: {{clamp.config.policy.pap.url}}/policy/pap/v1/pdps/deployments/batch"></log>
-            <toD
-                    uri="{{clamp.config.policy.pap.url}}/policy/pap/v1/pdps/deployments/batch?bridgeEndpoint=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;useSystemProperties=true&amp;authUsername={{clamp.config.policy.pap.userName}}&amp;authPassword={{clamp.config.policy.pap.password}}&amp;httpClient.connectTimeout=10000&amp;httpClient.socketTimeout=20000&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
-
+            <to uri="direct:add-multiple-policies-to-pdp-group"/>
             <doFinally>
-                <to uri="direct:reset-raise-http-exception-flag"/>
                 <to
                         uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
                 <setProperty propertyName="logMessage">
@@ -486,7 +463,43 @@
             </doFinally>
         </doTry>
     </route>
-
+    <route id="add-multiple-policies-to-pdp-group">
+        <from uri="direct:add-multiple-policies-to-pdp-group"/>
+        <!-- Body should come from outside, expect a json describing the policy -->
+        <doTry>
+            <log loggingLevel="INFO"
+                 message="Add policies to PDP group"/>
+            <to
+                    uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Add policies to PDP group')"/>
+            <setHeader headerName="CamelHttpMethod">
+                <constant>POST</constant>
+            </setHeader>
+            <setHeader headerName="Content-Type">
+                <constant>application/json</constant>
+            </setHeader>
+            <setHeader headerName="X-ONAP-RequestID">
+                <simple>${exchangeProperty[X-ONAP-RequestID]}
+                </simple>
+            </setHeader>
+            <setHeader headerName="X-ONAP-InvocationID">
+                <simple>${exchangeProperty[X-ONAP-InvocationID]}
+                </simple>
+            </setHeader>
+            <setHeader headerName="X-ONAP-PartnerName">
+                <simple>${exchangeProperty[X-ONAP-PartnerName]}
+                </simple>
+            </setHeader>
+            <log loggingLevel="INFO"
+                 message="Endpoint to add policies to PDP Group: {{clamp.config.policy.pap.url}}/policy/pap/v1/pdps/deployments/batch"></log>
+            <toD
+                    uri="{{clamp.config.policy.pap.url}}/policy/pap/v1/pdps/deployments/batch?bridgeEndpoint=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;useSystemProperties=true&amp;authUsername={{clamp.config.policy.pap.userName}}&amp;authPassword={{clamp.config.policy.pap.password}}&amp;httpClient.connectTimeout=10000&amp;httpClient.socketTimeout=20000&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+            <doFinally>
+                <to uri="direct:reset-raise-http-exception-flag"/>
+                <to
+                        uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+            </doFinally>
+        </doTry>
+    </route>
     <route id="undeploy-one-policy-from-pap">
         <from uri="direct:undeploy-one-policy-from-pap"/>
         <doTry>
diff --git a/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupAnalyzerTest.java b/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupAnalyzerTest.java
index e671741..c7ada58 100644
--- a/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupAnalyzerTest.java
+++ b/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupAnalyzerTest.java
@@ -25,9 +25,14 @@
 
 import static org.assertj.core.api.Assertions.assertThat;
 
+import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
 import org.onap.policy.clamp.loop.template.PolicyModel;
 import org.onap.policy.models.pdp.concepts.PdpGroup;
 import org.onap.policy.models.pdp.concepts.PdpGroups;
@@ -41,6 +46,15 @@
 public class PdpGroupAnalyzerTest {
 
     private static PdpGroups pdpGroups;
+    private static PdpGroup pdpGroup1;
+    private static PdpGroup pdpGroup2;
+    private static PdpGroup pdpGroup3;
+    private static PdpGroup pdpGroup4;
+
+    private static PdpSubGroup pdpSubgroupBad;
+    private static PdpSubGroup pdpSubgroup1;
+    private static PdpSubGroup pdpSubgroup2;
+    private static PdpSubGroup pdpSubgroup3;
 
     /**
      * This method preloads the pdpGroups for the tests.
@@ -49,7 +63,7 @@
     public static void setupPdpGroup() {
         // Create Pdp Groups
         // Those that do not work first
-        PdpSubGroup pdpSubgroupBad = new PdpSubGroup();
+        pdpSubgroupBad = new PdpSubGroup();
         pdpSubgroupBad.setPdpType("subGroupBad");
         pdpSubgroupBad.setSupportedPolicyTypes(Arrays.asList(new ToscaConceptIdentifier("org.onap.test", "2.0.0"),
                 new ToscaConceptIdentifier("org.onap.test.*", "1.0.0"),
@@ -58,50 +72,54 @@
                 new ToscaConceptIdentifier("org.onap.tes", "1.0.0"),
                 new ToscaConceptIdentifier("org.onap", "1.0.0")
         ));
-        pdpSubgroupBad.setPolicies(Arrays.asList(new ToscaConceptIdentifier("org.onap", "1.0.0")));
-        pdpSubgroupBad.setPolicies(Arrays.asList(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")));
-        pdpSubgroupBad.setPolicies(Arrays.asList(new ToscaConceptIdentifier("org.onap.testos", "1.0.1")));
-        pdpSubgroupBad.setPolicies(Arrays.asList(new ToscaConceptIdentifier("org.onap.testos.new", "1.0.0")));
-        pdpSubgroupBad.setPolicies(Arrays.asList(new ToscaConceptIdentifier("org.onap.*", "1.0.0")));
+        pdpSubgroupBad.setPolicies(Arrays.asList(new ToscaConceptIdentifier("org.onap", "1.0.0"),
+                new ToscaConceptIdentifier("org.onap.testos", "2.0.0"),
+                new ToscaConceptIdentifier("org.onap.testos", "1.0.1"),
+                new ToscaConceptIdentifier("org.onap.testos.new", "1.0.0"),
+                new ToscaConceptIdentifier("org.onap.", "1.0.0")));
+        pdpSubgroupBad.setPdpInstances(Collections.emptyList());
 
-        PdpSubGroup pdpSubgroup1 = new PdpSubGroup();
+        pdpSubgroup1 = new PdpSubGroup();
         pdpSubgroup1.setPdpType("subGroup1");
         pdpSubgroup1.setSupportedPolicyTypes(
                 Arrays.asList(new ToscaConceptIdentifier("org.onap.*", "1.0.0")));
+        pdpSubgroup1.setPdpInstances(Collections.emptyList());
 
-        PdpSubGroup pdpSubgroup2 = new PdpSubGroup();
+        pdpSubgroup2 = new PdpSubGroup();
         pdpSubgroup2.setPdpType("subGroup2");
         pdpSubgroup2.setSupportedPolicyTypes(Arrays.asList(new ToscaConceptIdentifier("org.onap.test", "1.0.0")));
         pdpSubgroup2.setPolicies(Arrays.asList(new ToscaConceptIdentifier("org.onap.testos", "1.0.0")));
+        pdpSubgroup2.setPdpInstances(Collections.emptyList());
 
-        PdpSubGroup pdpSubgroup3 = new PdpSubGroup();
+        pdpSubgroup3 = new PdpSubGroup();
         pdpSubgroup3.setPdpType("subGroup3");
         pdpSubgroup3.setSupportedPolicyTypes(Arrays.asList(new ToscaConceptIdentifier("org.onap.test*", "1.0.0")));
         pdpSubgroup3.setPolicies(Arrays.asList(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")));
+        pdpSubgroup3.setPdpInstances(Collections.emptyList());
 
         // Should match pdpSubgroup1
-        PdpGroup pdpGroup1 = new PdpGroup();
+        pdpGroup1 = new PdpGroup();
         pdpGroup1.setName("pdpGroup1");
         pdpGroup1.setPdpGroupState(PdpState.ACTIVE);
         pdpGroup1.setPdpSubgroups(Arrays.asList(pdpSubgroup1, pdpSubgroupBad));
 
         // Should match pdpSubgroup1, pdpSubgroup2, pdpSubgroup3
         // Should match also for the policy (pdpSubgroup2)
-        PdpGroup pdpGroup2 = new PdpGroup();
+        pdpGroup2 = new PdpGroup();
         pdpGroup2.setName("pdpGroup2");
         pdpGroup2.setPdpGroupState(PdpState.ACTIVE);
         pdpGroup2.setPdpSubgroups(Arrays.asList(pdpSubgroup1, pdpSubgroup2, pdpSubgroup3, pdpSubgroupBad));
 
         /// Should not match
-        PdpGroup pdpGroup3 = new PdpGroup();
+        pdpGroup3 = new PdpGroup();
         pdpGroup3.setName("pdpGroup3");
         pdpGroup3.setPdpGroupState(PdpState.ACTIVE);
         pdpGroup3.setPdpSubgroups(Arrays.asList(pdpSubgroupBad));
 
         // Should not match
-        PdpGroup pdpGroup4 = new PdpGroup();
+        pdpGroup4 = new PdpGroup();
         pdpGroup4.setName("pdpGroup4");
-        pdpGroup4.setPdpGroupState(PdpState.PASSIVE);
+        pdpGroup4.setPdpGroupState(PdpState.TERMINATED);
         pdpGroup4.setPdpSubgroups(Arrays.asList(pdpSubgroup1));
 
         pdpGroups = new PdpGroups();
@@ -109,6 +127,92 @@
     }
 
     @Test
+    public void testStructuresConstruction() {
+        PdpGroupsAnalyzer pdpGroupsAnalyzer = new PdpGroupsAnalyzer(pdpGroups);
+        assertThat(pdpGroupsAnalyzer).isNotNull();
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()).hasSize(6);
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "2.0.0"))).hasSize(3);
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")).get("pdpGroup1").getPdpSubgroups().size())
+                .isEqualTo(1);
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")).get("pdpGroup1").getPdpSubgroups())
+                .contains(pdpSubgroupBad);
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")).get("pdpGroup2").getPdpSubgroups().size())
+                .isEqualTo(2);
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")).get("pdpGroup2").getPdpSubgroups())
+                .contains(pdpSubgroup3);
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")).get("pdpGroup2").getPdpSubgroups())
+                .contains(pdpSubgroupBad);
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")).get("pdpGroup3").getPdpSubgroups().size())
+                .isEqualTo(1);
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")).get("pdpGroup3").getPdpSubgroups())
+                .contains(pdpSubgroupBad);
+
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.0"))).hasSize(1);
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.0")).get("pdpGroup2").getPdpSubgroups().size())
+                .isEqualTo(1);
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.0")).get("pdpGroup2").getPdpSubgroups())
+                .contains(pdpSubgroup2);
+
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.1"))).hasSize(3);
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.1")).get("pdpGroup1").getPdpSubgroups().size())
+                .isEqualTo(1);
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.1")).get("pdpGroup1").getPdpSubgroups())
+                .contains(pdpSubgroupBad);
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.1")).get("pdpGroup2").getPdpSubgroups().size())
+                .isEqualTo(1);
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.1")).get("pdpGroup2").getPdpSubgroups())
+                .contains(pdpSubgroupBad);
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.1")).get("pdpGroup3").getPdpSubgroups().size())
+                .isEqualTo(1);
+        assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+                .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.1")).get("pdpGroup3").getPdpSubgroups())
+                .contains(pdpSubgroupBad);
+    }
+
+    @Test
+    public void testGetSupportedPdpGroupsForPolicy() throws IOException {
+        PolicyModel policyModel = new PolicyModel();
+        policyModel.setCreatedBy("user");
+        policyModel.setPolicyAcronym("TEST");
+        policyModel.setPolicyModelTosca("yaml");
+        policyModel.setPolicyModelType("org.onap.test");
+        policyModel.setUpdatedBy("user");
+        policyModel.setVersion("1.0.0");
+
+        PdpGroupsAnalyzer pdpGroupsAnalyzer = new PdpGroupsAnalyzer(pdpGroups);
+        assertThat(pdpGroupsAnalyzer).isNotNull();
+
+        assertThat(
+                JsonUtils.GSON.toJson(pdpGroupsAnalyzer.getPdpGroupsForPolicy("org.onap.testos", "2.0.0")))
+                .isEqualTo(ResourceFileUtils.getResourceAsString("example/policy/pdp-deployment-testos-2_0_0.json"));
+
+        assertThat(
+                JsonUtils.GSON.toJson(pdpGroupsAnalyzer.getPdpGroupsForPolicy("org.onap.testos", "1.0.0")))
+                .isEqualTo(ResourceFileUtils.getResourceAsString("example/policy/pdp-deployment-testos-1_0_0.json"));
+
+        assertThat(
+                pdpGroupsAnalyzer.getPdpGroupsForPolicy("org.onap.donotexist", "1.0.0"))
+                .isNull();
+    }
+
+    @Test
     public void testUpdatePdpGroupOfPolicyModels() {
         // Create policyModel
         PolicyModel policyModel = new PolicyModel();
@@ -120,22 +224,8 @@
         policyModel.setVersion("1.0.0");
         PdpGroupsAnalyzer.updatePdpGroupOfPolicyModels(Arrays.asList(policyModel), pdpGroups);
 
-        assertThat(policyModel.getPolicyPdpGroup().toString()).isEqualTo(
+        assertThat(policyModel.getPolicyPdpGroup()).hasToString(
                 "{\"supportedPdpGroups\":[{\"pdpGroup1\":[\"subGroup1\"]},"
                         + "{\"pdpGroup2\":[\"subGroup1\",\"subGroup2\",\"subGroup3\"]}]}");
     }
-
-    @Test
-    public void testGetPdpGroupDeploymentsOfOnePolicy() {
-        assertThat(
-                PdpGroupsAnalyzer.getPdpGroupDeploymentOfOnePolicy(pdpGroups, "org.onap.testos", "1.0.0").toString())
-                .isEqualTo("{\"pdpGroupInfo\":{\"pdpGroup\":\"pdpGroup2\",\"pdpSubGroup\":\"subGroup2\"}}");
-    }
-
-    @Test
-    public void testGetPdpGroupDeploymentsOfOnePolicyNull() {
-        assertThat(
-                PdpGroupsAnalyzer.getPdpGroupDeploymentOfOnePolicy(pdpGroups, "org.onap.DoNotExist", "1.0.0"))
-                .isNull();
-    }
 }
diff --git a/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMergerTest.java b/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMergerTest.java
index 7b8cbd8..be7a9d6 100644
--- a/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMergerTest.java
+++ b/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMergerTest.java
@@ -93,20 +93,10 @@
     }
 
     @Test
-    public void testUpdatePdpGroupOfPolicyModels() throws IOException {
+    public void testMergePoliciesAndPdpGroupStates() throws IOException {
         JSONAssert.assertEquals(ResourceFileUtils.getResourceAsString("example/policy/policy-merger.json"),
                 PoliciesPdpMerger.mergePoliciesAndPdpGroupStates(
                         ResourceFileUtils.getResourceAsString("http-cache/example/policy/api/v1/policies/.file"),
                         pdpGroupsJson).toString(), true);
     }
-
-    @Test
-    public void testRemovePdpStatesOnePolicy() throws IOException {
-        JsonObject policiesList = PoliciesPdpMerger.removePdpStatesOnePolicy(JsonUtils.GSON.fromJson(
-                ResourceFileUtils.getResourceAsString("example/policy/single-policy-enriched.json"), JsonObject.class));
-
-        assertThat(policiesList.get(PdpGroupsAnalyzer.ASSIGNED_PDP_GROUPS_INFO)).isNull();
-        assertThat(policiesList.get(PdpGroupsAnalyzer.SUPPORTED_PDP_GROUPS_INFO)).isNull();
-        assertThat(policiesList.size()).isEqualTo(6);
-    }
 }
diff --git a/src/test/resources/example/policy/pdp-deployment-testos-1_0_0.json b/src/test/resources/example/policy/pdp-deployment-testos-1_0_0.json
new file mode 100644
index 0000000..3b4a0ea
--- /dev/null
+++ b/src/test/resources/example/policy/pdp-deployment-testos-1_0_0.json
@@ -0,0 +1,30 @@
+{
+  "pdpGroupInfo": [
+    {
+      "pdpGroup2": {
+        "name": "pdpGroup2",
+        "pdpGroupState": "ACTIVE",
+        "pdpSubgroups": [
+          {
+            "pdpType": "subGroup2",
+            "supportedPolicyTypes": [
+              {
+                "name": "org.onap.test",
+                "version": "1.0.0"
+              }
+            ],
+            "policies": [
+              {
+                "name": "org.onap.testos",
+                "version": "1.0.0"
+              }
+            ],
+            "currentInstanceCount": 0,
+            "desiredInstanceCount": 0,
+            "pdpInstances": []
+          }
+        ]
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/src/test/resources/example/policy/pdp-deployment-testos-2_0_0.json b/src/test/resources/example/policy/pdp-deployment-testos-2_0_0.json
new file mode 100644
index 0000000..0040052
--- /dev/null
+++ b/src/test/resources/example/policy/pdp-deployment-testos-2_0_0.json
@@ -0,0 +1,204 @@
+{
+  "pdpGroupInfo": [
+    {
+      "pdpGroup3": {
+        "name": "pdpGroup3",
+        "pdpGroupState": "ACTIVE",
+        "pdpSubgroups": [
+          {
+            "pdpType": "subGroupBad",
+            "supportedPolicyTypes": [
+              {
+                "name": "org.onap.test",
+                "version": "2.0.0"
+              },
+              {
+                "name": "org.onap.test.*",
+                "version": "1.0.0"
+              },
+              {
+                "name": "org.onip.testos",
+                "version": "1.0.0"
+              },
+              {
+                "name": "org.onap.testos3",
+                "version": "2.0.0"
+              },
+              {
+                "name": "org.onap.tes",
+                "version": "1.0.0"
+              },
+              {
+                "name": "org.onap",
+                "version": "1.0.0"
+              }
+            ],
+            "policies": [
+              {
+                "name": "org.onap",
+                "version": "1.0.0"
+              },
+              {
+                "name": "org.onap.testos",
+                "version": "2.0.0"
+              },
+              {
+                "name": "org.onap.testos",
+                "version": "1.0.1"
+              },
+              {
+                "name": "org.onap.testos.new",
+                "version": "1.0.0"
+              },
+              {
+                "name": "org.onap.",
+                "version": "1.0.0"
+              }
+            ],
+            "currentInstanceCount": 0,
+            "desiredInstanceCount": 0,
+            "pdpInstances": []
+          }
+        ]
+      },
+      "pdpGroup1": {
+        "name": "pdpGroup1",
+        "pdpGroupState": "ACTIVE",
+        "pdpSubgroups": [
+          {
+            "pdpType": "subGroupBad",
+            "supportedPolicyTypes": [
+              {
+                "name": "org.onap.test",
+                "version": "2.0.0"
+              },
+              {
+                "name": "org.onap.test.*",
+                "version": "1.0.0"
+              },
+              {
+                "name": "org.onip.testos",
+                "version": "1.0.0"
+              },
+              {
+                "name": "org.onap.testos3",
+                "version": "2.0.0"
+              },
+              {
+                "name": "org.onap.tes",
+                "version": "1.0.0"
+              },
+              {
+                "name": "org.onap",
+                "version": "1.0.0"
+              }
+            ],
+            "policies": [
+              {
+                "name": "org.onap",
+                "version": "1.0.0"
+              },
+              {
+                "name": "org.onap.testos",
+                "version": "2.0.0"
+              },
+              {
+                "name": "org.onap.testos",
+                "version": "1.0.1"
+              },
+              {
+                "name": "org.onap.testos.new",
+                "version": "1.0.0"
+              },
+              {
+                "name": "org.onap.",
+                "version": "1.0.0"
+              }
+            ],
+            "currentInstanceCount": 0,
+            "desiredInstanceCount": 0,
+            "pdpInstances": []
+          }
+        ]
+      },
+      "pdpGroup2": {
+        "name": "pdpGroup2",
+        "pdpGroupState": "ACTIVE",
+        "pdpSubgroups": [
+          {
+            "pdpType": "subGroup3",
+            "supportedPolicyTypes": [
+              {
+                "name": "org.onap.test*",
+                "version": "1.0.0"
+              }
+            ],
+            "policies": [
+              {
+                "name": "org.onap.testos",
+                "version": "2.0.0"
+              }
+            ],
+            "currentInstanceCount": 0,
+            "desiredInstanceCount": 0,
+            "pdpInstances": []
+          },
+          {
+            "pdpType": "subGroupBad",
+            "supportedPolicyTypes": [
+              {
+                "name": "org.onap.test",
+                "version": "2.0.0"
+              },
+              {
+                "name": "org.onap.test.*",
+                "version": "1.0.0"
+              },
+              {
+                "name": "org.onip.testos",
+                "version": "1.0.0"
+              },
+              {
+                "name": "org.onap.testos3",
+                "version": "2.0.0"
+              },
+              {
+                "name": "org.onap.tes",
+                "version": "1.0.0"
+              },
+              {
+                "name": "org.onap",
+                "version": "1.0.0"
+              }
+            ],
+            "policies": [
+              {
+                "name": "org.onap",
+                "version": "1.0.0"
+              },
+              {
+                "name": "org.onap.testos",
+                "version": "2.0.0"
+              },
+              {
+                "name": "org.onap.testos",
+                "version": "1.0.1"
+              },
+              {
+                "name": "org.onap.testos.new",
+                "version": "1.0.0"
+              },
+              {
+                "name": "org.onap.",
+                "version": "1.0.0"
+              }
+            ],
+            "currentInstanceCount": 0,
+            "desiredInstanceCount": 0,
+            "pdpInstances": []
+          }
+        ]
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/src/test/resources/example/policy/policy-merger.json b/src/test/resources/example/policy/policy-merger.json
index e1424ff..c3291ef 100644
--- a/src/test/resources/example/policy/policy-merger.json
+++ b/src/test/resources/example/policy/policy-merger.json
@@ -34,10 +34,38 @@
         "policy-id": "MICROSERVICE_vLoadBalancerMS_v1_0_tcagen2_1_0_0_AV0",
         "policy-version": "1.0.0"
       },
-      "pdpGroupInfo": {
-        "pdpGroup": "pdpGroup2",
-        "pdpSubGroup": "subGroup2"
-      },
+      "pdpGroupInfo": [
+        {
+          "pdpGroup2": {
+            "name": "pdpGroup2",
+            "pdpGroupState": "ACTIVE",
+            "pdpSubgroups": [
+              {
+                "pdpType": "subGroup2",
+                "supportedPolicyTypes": [
+                  {
+                    "name": "onap.policies.monitoring.tcagen2",
+                    "version": "1.0.0"
+                  },
+                  {
+                    "name": "onap.policies.controlloop.operational.common.Drools",
+                    "version": "1.0.0"
+                  }
+                ],
+                "policies": [
+                  {
+                    "name": "MICROSERVICE_vLoadBalancerMS_v1_0_tcagen2_1_0_0_AV0",
+                    "version": "1.0.0"
+                  }
+                ],
+                "currentInstanceCount": 0,
+                "desiredInstanceCount": 0,
+                "pdpInstances": []
+              }
+            ]
+          }
+        }
+      ],
       "supportedPdpGroups": [
         {
           "pdpGroup2": [
@@ -97,10 +125,42 @@
         "policy-id": "OPERATIONAL_vLoadBalancerMS_v1_0_Drools_1_0_0_7xd",
         "policy-version": "1.0.0"
       },
-      "pdpGroupInfo": {
-        "pdpGroup": "pdpGroup2",
-        "pdpSubGroup": "subGroup3"
-      },
+      "pdpGroupInfo": [
+        {
+          "pdpGroup2": {
+            "name": "pdpGroup2",
+            "pdpGroupState": "ACTIVE",
+            "pdpSubgroups": [
+              {
+                "pdpType": "subGroup3",
+                "supportedPolicyTypes": [
+                  {
+                    "name": "onap.policies.monitoring.tcagen2",
+                    "version": "1.0.0"
+                  },
+                  {
+                    "name": "onap.policies.controlloop.operational.common.Drools",
+                    "version": "1.0.0"
+                  }
+                ],
+                "policies": [
+                  {
+                    "name": "org.onap.testos",
+                    "version": "2.0.0"
+                  },
+                  {
+                    "name": "OPERATIONAL_vLoadBalancerMS_v1_0_Drools_1_0_0_7xd",
+                    "version": "1.0.0"
+                  }
+                ],
+                "currentInstanceCount": 0,
+                "desiredInstanceCount": 0,
+                "pdpInstances": []
+              }
+            ]
+          }
+        }
+      ],
       "supportedPdpGroups": [
         {
           "pdpGroup2": [
diff --git a/src/test/resources/http-cache/example/policy/pap/v1/pdps/.file b/src/test/resources/http-cache/example/policy/pap/v1/pdps/.file
index b0d6819..467409f 100644
--- a/src/test/resources/http-cache/example/policy/pap/v1/pdps/.file
+++ b/src/test/resources/http-cache/example/policy/pap/v1/pdps/.file
@@ -10,7 +10,12 @@
                     "desiredInstanceCount": 1,
                     "pdpInstances": [],
                     "pdpType": "apex",
-                    "policies": [],
+                    "policies": [
+                                {
+                                  "name": "OPERATIONAL_vLoadBalancerMS_v1_0_Drools_1_0_0_7xd",
+                                  "version": "1.0.0"
+                                }
+                    ],
                     "properties": {},
                     "supportedPolicyTypes": [
                         {
diff --git a/ui-react-lib/libIndex.js b/ui-react-lib/libIndex.js
index 8772421..1ad0c9e 100755
--- a/ui-react-lib/libIndex.js
+++ b/ui-react-lib/libIndex.js
@@ -52,3 +52,4 @@
 export { default as UserService } from './src/api/UserService';
 export { default as ViewLoopTemplatesModal } from './src/components/dialogs/Tosca/ViewLoopTemplatesModal';
 export { default as ViewAllPolicies } from './src/components/dialogs/Policy/ViewAllPolicies';
+export { default as PolicyDeploymentEditor } from './src/components/dialogs/Policy/PolicyDeploymentEditor';
diff --git a/ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor.js b/ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor.js
new file mode 100644
index 0000000..da695ee
--- /dev/null
+++ b/ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor.js
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights
+ *                             reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+import React, { forwardRef } from 'react';
+import Modal from 'react-bootstrap/Modal';
+import styled from 'styled-components';
+import Button from 'react-bootstrap/Button';
+
+const ModalStyled = styled(Modal)`
+    @media (min-width: 500px) {
+        .modal-xl {
+            max-width: 50%;
+        }
+    }
+    background-color: transparent;
+`
+
+export default class PolicyDeploymentEditor extends React.Component {
+
+    state = {
+            policyData: this.props.policyData,
+    };
+
+    constructor(props, context) {
+        super(props, context);
+        this.handleClose = this.handleClose.bind(this);
+    }
+
+    handleClose() {
+        this.setState({ show: false });
+
+    }
+
+    render() {
+     return (
+             <ModalStyled size="xl" show={this.state.show} onHide={this.handleClose} backdrop="static" keyboard={false}>
+                 <Modal.Header closeButton>
+                 </Modal.Header>
+
+                 <Modal.Footer>
+                     <Button variant="secondary" onClick={this.handleClose}>Close</Button>
+                </Modal.Footer>
+             </ModalStyled>
+       );
+    }
+ }
\ No newline at end of file
diff --git a/ui-react/src/components/dialogs/Policy/ViewAllPolicies.js b/ui-react/src/components/dialogs/Policy/ViewAllPolicies.js
index d699f78..48d52a1 100644
--- a/ui-react/src/components/dialogs/Policy/ViewAllPolicies.js
+++ b/ui-react/src/components/dialogs/Policy/ViewAllPolicies.js
@@ -43,24 +43,26 @@
 import DehazeIcon from '@material-ui/icons/Dehaze';
 import ArrowForwardIosIcon from '@material-ui/icons/ArrowForwardIos';
 import AddIcon from '@material-ui/icons/Add';
+import PublishIcon from '@material-ui/icons/Publish';
 import FormControlLabel from '@material-ui/core/FormControlLabel';
 import Switch from '@material-ui/core/Switch';
 import MaterialTable from "material-table";
 import PolicyService from '../../../api/PolicyService';
 import PolicyToscaService from '../../../api/PolicyToscaService';
-import Select from 'react-select';
+import Select from '@material-ui/core/Select';
 import Alert from 'react-bootstrap/Alert';
 import Tabs from 'react-bootstrap/Tabs';
 import Tab from 'react-bootstrap/Tab';
 import PolicyEditor from './PolicyEditor';
 import ToscaViewer from './ToscaViewer';
+import PolicyDeploymentEditor from './PolicyDeploymentEditor';
 
 const DivWhiteSpaceStyled = styled.div`
     white-space: pre;
 `
 
 const ModalStyled = styled(Modal)`
-    @media (min-width: 1000px) {
+    @media (min-width: 800px) {
         .modal-xl {
             max-width: 96%;
         }
@@ -78,13 +80,13 @@
 
 
 const standardCellStyle = { backgroundColor: '#039be5', color: '#FFF', border: '1px solid black' };
-const cellPdpGroupStyle = { backgroundColor: '#039be5', color: '#FFF', border: '1px solid black'};
-const headerStyle = { backgroundColor: '#ddd',    border: '2px solid black' };
-const rowHeaderStyle = {backgroundColor:'#ddd',  fontSize: '15pt', text: 'bold', border: '1px solid black'};
+const headerStyle = { backgroundColor: '#ddd', border: '2px solid black' };
+const rowHeaderStyle = {backgroundColor:'#ddd', fontSize: '15pt', text: 'bold', border: '1px solid black'};
 
 export default class ViewAllPolicies extends React.Component {
   state = {
         show: true,
+        showPolicyDeploymentDialog: false,
         content: 'Please select a policy to display it',
         selectedRowId: -1,
         policiesListData: [],
@@ -102,7 +104,7 @@
             {
                 title: "Policy Version", field: "version",
                 cellStyle: standardCellStyle,
-                headerStyle: headerStyle
+                headerStyle: headerStyle,
             },
             {
                 title: "Policy Type", field: "type",
@@ -115,20 +117,13 @@
                 headerStyle: headerStyle
             },
             {
-                title: "Deployed in PDP", field: "pdpGroupInfo.pdpGroup",
-                cellStyle: cellPdpGroupStyle,
-                headerStyle: headerStyle,
-                render: rowData => this.renderPdpGroupDropBox(rowData),
-                grouping: false
-            },
-            {
-                title: "PDP Group", field: "pdpGroupInfo.pdpGroup",
-                cellStyle: cellPdpGroupStyle,
+                title: "Deployable in PDP Group", field: "supportedPdpGroupsString",
+                cellStyle: standardCellStyle,
                 headerStyle: headerStyle
             },
             {
-                title: "PDP SubGroup", field: "pdpGroupInfo.pdpSubGroup",
-                cellStyle: cellPdpGroupStyle,
+                title: "Deployed in PDP Group", field: "pdpGroupInfoString",
+                cellStyle: standardCellStyle,
                 headerStyle: headerStyle
             }
         ],
@@ -183,58 +178,54 @@
     constructor(props, context) {
         super(props, context);
         this.handleClose = this.handleClose.bind(this);
-        this.renderPdpGroupDropBox = this.renderPdpGroupDropBox.bind(this);
-        this.handlePdpGroupChange = this.handlePdpGroupChange.bind(this);
         this.handlePrefixGrouping = this.handlePrefixGrouping.bind(this);
         this.handleDeletePolicy = this.handleDeletePolicy.bind(this);
         this.disableAlert = this.disableAlert.bind(this);
         this.getAllPolicies = this.getAllPolicies.bind(this);
         this.getAllToscaModels = this.getAllToscaModels.bind(this);
+        this.generateAdditionalPolicyColumns = this.generateAdditionalPolicyColumns.bind(this);
         this.getAllPolicies();
         this.getAllToscaModels();
     }
 
+    generateAdditionalPolicyColumns(policiesData) {
+        policiesData.forEach(policy => {
+            let supportedPdpGroupsString = "";
+            if (typeof policy.supportedPdpGroups !== "undefined") {
+                for (const pdpGroup of policy["supportedPdpGroups"]) {
+                    for (const pdpSubGroup of Object.values(pdpGroup)[0]) {
+                        supportedPdpGroupsString += (Object.keys(pdpGroup)[0] + "/" + pdpSubGroup + "\r\n");
+                    }
+                }
+                policy["supportedPdpGroupsString"] = supportedPdpGroupsString;
+            }
+
+            let infoPdpGroup = "";
+            if (typeof policy.pdpGroupInfo !== "undefined") {
+                policy["pdpGroupInfo"].forEach(pdpGroupElem => {
+                    let groupName = Object.keys(pdpGroupElem)[0];
+                    pdpGroupElem[groupName]["pdpSubgroups"].forEach(pdpSubGroupElem => {
+                        infoPdpGroup +=  (groupName + "/" + pdpSubGroupElem["pdpType"] + " ("
+                            + pdpGroupElem[groupName]["pdpGroupState"] + ")" + "\r\n");
+                    });
+                    policy["pdpGroupInfoString"] = infoPdpGroup;
+                });
+            }
+        });
+    }
+
     getAllToscaModels() {
         PolicyToscaService.getToscaPolicyModels().then(toscaModelsList => {
             this.setState({ toscaModelsListData: toscaModelsList });
         });
     }
 
-    handlePdpGroupChange(e) {
-        let pdpSplit = e.value.split("/");
-        let selectedPdpGroup = pdpSplit[0];
-        let selectedSubPdpGroup = pdpSplit[1];
-        if (typeof selectedSubPdpGroup !== "undefined") {
-            let temp = this.state.policiesListData;
-            temp[this.state.selectedRowId]["pdpGroupInfo"] = {"pdpGroup":selectedPdpGroup,"pdpSubGroup":selectedSubPdpGroup};
-            this.setState({policiesListData: temp});
-        } else {
-            delete this.state.policiesListData[this.state.selectedRowId]["pdpGroupInfo"];
-        }
-    }
-
-    renderPdpGroupDropBox(dataRow) {
-        let optionItems = [{label: "NOT DEPLOYED", value: "NOT DEPLOYED"}];
-        let selectedItem = {label: "NOT DEPLOYED", value: "NOT DEPLOYED"};
-        if (typeof dataRow.supportedPdpGroups !== "undefined") {
-            for (const pdpGroup of dataRow["supportedPdpGroups"]) {
-                for (const pdpSubGroup of Object.values(pdpGroup)[0]) {
-                    optionItems.push({ label: Object.keys(pdpGroup)[0]+"/"+pdpSubGroup,
-                    value: Object.keys(pdpGroup)[0]+"/"+pdpSubGroup });
-                }
-            }
-        }
-        if (typeof dataRow.pdpGroupInfo !== "undefined") {
-            selectedItem = {label: dataRow["pdpGroupInfo"]["pdpGroup"]+"/"+dataRow["pdpGroupInfo"]["pdpSubGroup"],
-            value: dataRow["pdpGroupInfo"]["pdpGroup"]+"/"+dataRow["pdpGroupInfo"]["pdpSubGroup"]};
-        }
-        return (<div style={{width: '250px'}}><Select value={selectedItem} options={optionItems} onChange={this.handlePdpGroupChange}/></div>);
-    }
-
     getAllPolicies() {
         PolicyService.getPoliciesList().then(allPolicies => {
+            this.generateAdditionalPolicyColumns(allPolicies["policies"])
             this.setState({ policiesListData: allPolicies["policies"] })
         });
+
     }
 
     handleClose() {
@@ -316,6 +307,15 @@
                                     )
                                   },
                                 },
+                                {
+                                  icon: PublishIcon,
+                                  tooltip: 'PDP Group Deployment',
+                                  render: rowData => {
+                                    return (
+                                        <PolicyDeploymentEditor policyData={rowData}/>
+                                    )
+                                  },
+                                }
                               ]}
                               actions={[
                                   {
@@ -416,7 +416,7 @@
                 <Modal.Footer>
                     <Button variant="secondary" onClick={this.handleClose}>Close</Button>
                </Modal.Footer>
-      </ModalStyled>
+            </ModalStyled>
       );
     }
   }
\ No newline at end of file