Merge "Fix minor checksyle issues in models"
diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfTimestampKey.java b/models-base/src/main/java/org/onap/policy/models/base/PfTimestampKey.java
new file mode 100644
index 0000000..a2f1129
--- /dev/null
+++ b/models-base/src/main/java/org/onap/policy/models/base/PfTimestampKey.java
@@ -0,0 +1,156 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import java.util.Date;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NonNull;
+import org.onap.policy.common.utils.validation.Assertions;
+
+@Embeddable
+@Getter
+@EqualsAndHashCode(callSuper = false)
+public class PfTimestampKey extends PfKeyImpl {
+    private static final long serialVersionUID = -8410208962541783805L;
+
+    private static final String TIMESTAMP_TOKEN = "timeStamp";
+
+    @Column(name = NAME_TOKEN, length = 120)
+    private String name;
+
+    @Column(name = VERSION_TOKEN, length = 20)
+    private String version;
+
+    @Column(name = TIMESTAMP_TOKEN)
+    private Date timeStamp;
+
+
+    /**
+     * The default constructor creates a null concept key.
+     */
+    public PfTimestampKey() {
+        this(NULL_KEY_NAME, NULL_KEY_VERSION, new Date(0));
+    }
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public PfTimestampKey(@NonNull final PfTimestampKey copyConcept) {
+        super(copyConcept);
+        this.timeStamp = new Date(copyConcept.getTimeStamp().getTime());
+    }
+
+    /**
+     * Constructor to create a key with the specified name and version.
+     *
+     * @param name the key name
+     * @param version the key version
+     * @param timeStamp the timestamp of key
+     */
+    public PfTimestampKey(@NonNull final String name, @NonNull final String version,
+            @NonNull final Date timeStamp) {
+        super(name, version);
+        this.timeStamp = new Date(timeStamp.getTime());
+    }
+
+    /**
+     * Constructor to create a key using the key and version from the specified key ID.
+     *
+     * @param id the key ID in a format that respects the KEY_ID_REGEXP
+     */
+    public PfTimestampKey(final String id) {
+        super(id.substring(0, id.lastIndexOf(':')));
+        this.timeStamp = new Date(Long.parseLong(id.substring(id.lastIndexOf(':') + 1)));
+    }
+
+    @Override
+    public String getId() {
+        return getName() + ':' + getVersion() + ':' + getTimeStamp().getTime();
+    }
+
+    /**
+     * Get a null key.
+     *
+     * @return a null key
+     */
+    public static final PfTimestampKey getNullKey() {
+        return new PfTimestampKey(PfKey.NULL_KEY_NAME, PfKey.NULL_KEY_VERSION, new Date(0));
+    }
+
+    @Override
+    public String toString() {
+        return "PfTimestampKey(name=" + getName() + ", version=" + getVersion() + ", timestamp="
+                + getTimeStamp().getTime() + ")";
+    }
+
+    @Override
+    public boolean isNewerThan(@NonNull PfKey otherKey) {
+        Assertions.instanceOf(otherKey, PfTimestampKey.class);
+
+        final PfTimestampKey otherConceptKey = (PfTimestampKey) otherKey;
+
+        if (this.equals(otherConceptKey)) {
+            return false;
+        }
+
+        if (!timeStamp.equals(otherConceptKey.timeStamp)) {
+            return timeStamp.after(otherConceptKey.timeStamp);
+        }
+
+        return super.isNewerThan(otherKey);
+    }
+
+    public void setTimeStamp(@NonNull final Date timeStamp) {
+        this.timeStamp = new Date(timeStamp.getTime());
+    }
+
+    @Override
+    public boolean isNullKey() {
+        return super.isNullKey() && getTimeStamp().getTime() == 0;
+    }
+
+    @Override
+    public int compareTo(@NonNull final PfConcept otherObj) {
+        int result = super.compareTo(otherObj);
+        if (0 == result) {
+            final PfTimestampKey other = (PfTimestampKey) otherObj;
+            return timeStamp.compareTo(other.timeStamp);
+        }
+        return result;
+    }
+
+    @Override
+    public void setName(@NonNull String name) {
+        this.name = Assertions.validateStringParameter(NAME_TOKEN, name, getNameRegEx());
+    }
+
+    @Override
+    public void setVersion(@NonNull String version) {
+        this.version = Assertions.validateStringParameter(VERSION_TOKEN, version, getVersionRegEx());
+    }
+}
diff --git a/models-base/src/test/java/org/onap/policy/models/base/PfTimestampKeyTest.java b/models-base/src/test/java/org/onap/policy/models/base/PfTimestampKeyTest.java
new file mode 100644
index 0000000..28b9fd9
--- /dev/null
+++ b/models-base/src/test/java/org/onap/policy/models/base/PfTimestampKeyTest.java
@@ -0,0 +1,95 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.base;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Date;
+import org.junit.Test;
+
+public class PfTimestampKeyTest {
+    private static final String VERSION001 = "0.0.1";
+    private static final String CONCEPT_IS_NULL = "copyConcept is marked @NonNull but is null";
+    private static final String NAME_IS_NULL = "name is marked @NonNull but is null";
+    private static final String VERSION_IS_NULL = "version is marked @NonNull but is null";
+    private static final String TIMESTAMP_IS_NULL = "timeStamp is marked @NonNull but is null";
+    private static final long timeStamp = 1574832537641L;
+
+    @Test
+    public void testTimestampKey() {
+        PfTimestampKey someKey0 = new PfTimestampKey();
+        assertEquals(PfTimestampKey.getNullKey(), someKey0);
+        assertTrue(someKey0.isNullKey());
+        assertEquals("PfTimestampKey(name=NULL, version=0.0.0, timestamp=0)", someKey0.toString());
+
+        PfTimestampKey someKey1 = new PfTimestampKey("my-name", VERSION001, new Date(timeStamp));
+        PfTimestampKey someKey2 = new PfTimestampKey(someKey1);
+        PfTimestampKey someKey3 = new PfTimestampKey(someKey1.getId());
+        assertEquals(someKey1, someKey2);
+        assertEquals(someKey1, someKey3);
+        assertFalse(someKey1.isNullVersion());
+        assertEquals("PfTimestampKey(name=my-name, version=0.0.1, timestamp=1574832537641)", someKey1.toString());
+
+        assertEquals("my-name", someKey1.getName());
+        assertEquals(VERSION001, someKey1.getVersion());
+
+        assertEquals(someKey2, someKey1.getKey());
+        assertEquals(1, someKey1.getKeys().size());
+
+        assertThatThrownBy(() -> new PfTimestampKey((PfTimestampKey) null)).isInstanceOf(NullPointerException.class)
+                .hasMessage(CONCEPT_IS_NULL);
+        assertThatThrownBy(() -> new PfTimestampKey(null, null, null)).isInstanceOf(NullPointerException.class)
+                .hasMessage(NAME_IS_NULL);
+        assertThatThrownBy(() -> new PfTimestampKey("my-name", null, null)).isInstanceOf(NullPointerException.class)
+                .hasMessage(VERSION_IS_NULL);
+        assertThatThrownBy(() -> new PfTimestampKey("my-name", VERSION001, null))
+                .isInstanceOf(NullPointerException.class).hasMessage(TIMESTAMP_IS_NULL);
+
+        assertThatThrownBy(() -> someKey0.setName(null)).isInstanceOf(NullPointerException.class)
+                .hasMessage(NAME_IS_NULL);
+        assertThatThrownBy(() -> someKey0.setVersion(null)).isInstanceOf(NullPointerException.class)
+                .hasMessage(VERSION_IS_NULL);
+        assertThatThrownBy(() -> someKey0.setTimeStamp(null)).isInstanceOf(NullPointerException.class)
+                .hasMessage(TIMESTAMP_IS_NULL);
+
+        assertFalse(someKey1.isNewerThan(someKey2));
+        assertThatThrownBy(() -> someKey1.isNewerThan((PfKey) null)).isInstanceOf(NullPointerException.class)
+                .hasMessage("otherKey is marked @NonNull but is null");
+        someKey2.setTimeStamp(new Date(timeStamp + 1));
+        assertTrue(someKey2.isNewerThan(someKey1));
+        someKey3.setName("my-name3");
+        assertTrue(someKey3.isNewerThan(someKey1));
+
+        assertEquals(-1, someKey1.compareTo(someKey2));
+        assertEquals(-1, someKey1.compareTo(someKey3));
+        assertThatThrownBy(() -> someKey1.compareTo((PfConcept) null)).isInstanceOf(NullPointerException.class)
+                .hasMessage("otherObj is marked @NonNull but is null");
+
+        PfTimestampKey someKey4 = new PfTimestampKey("NULL", "0.0.0", new Date(timeStamp));
+        assertFalse(someKey4.isNullKey());
+        assertFalse(someKey1.isNullKey());
+    }
+}
diff --git a/models-examples/src/main/resources/policies/sdnc.policy.naming.input.tosca.yaml b/models-examples/src/main/resources/policies/sdnc.policy.naming.input.tosca.yaml
index 825e95d..f17e909 100644
--- a/models-examples/src/main/resources/policies/sdnc.policy.naming.input.tosca.yaml
+++ b/models-examples/src/main/resources/policies/sdnc.policy.naming.input.tosca.yaml
@@ -4,6 +4,7 @@
     -   SDNC_Policy.ONAP_VNF_NAMING_TIMESTAMP:
             type: onap.policies.Naming
             version: 1.0.0
+            type_version: 1.0.0
             properties:
                 policy-instance-name: ONAP_VNF_NAMING_TIMESTAMP
                 naming-models:
@@ -46,4 +47,4 @@
                             start-value: 1
                             length: 3
                             increment: 1
-                            sequence-type: alpha-numeric
\ No newline at end of file
+                            sequence-type: alpha-numeric
diff --git a/models-examples/src/main/resources/policies/vCPE.policies.optimization.input.tosca.json b/models-examples/src/main/resources/policies/vCPE.policies.optimization.input.tosca.json
index 68e3a44..929e29e 100644
--- a/models-examples/src/main/resources/policies/vCPE.policies.optimization.input.tosca.json
+++ b/models-examples/src/main/resources/policies/vCPE.policies.optimization.input.tosca.json
@@ -3,70 +3,231 @@
     "topology_template": {
         "policies": [
             {
-                "OSDF_CASABLANCA.Affinity_vCPE_1": {
-                    "type": "onap.policies.optimization.AffinityPolicy",
+                "OSDF_CASABLANCA.Affinity_Default": {
+                    "type": "onap.policies.optimization.resource.AffinityPolicy",
                     "version": "1.0.0",
+                    "type_version": "1.0.0",
                     "metadata": {
-                        "policy-id": "OSDF_CASABLANCA.Affinity_vCPE_1"
+                        "policy-id": "OSDF_CASABLANCA.Affinity_Default",
+                        "policy-version": 1
                     },
                     "properties": {
+                        "scope": [],
+                        "services": [],
+                        "resources": [],
+                        "geography": [],
                         "identity": "affinity_vCPE",
-                        "policyScope": [
-                            "vCPE",
-                            "US",
-                            "INTERNATIONAL",
-                            "ip",
-                            "vGMuxInfra",
-                            "vG"
-                        ],
+                        "applicableResources": "any",
                         "affinityProperties": {
                             "qualifier": "same",
                             "category": "complex"
-                        },
-                        "policyType": "zone",
+                        }
+                    }
+                }
+            },
+            {
+                "OSDF_CASABLANCA.Affinity_Default_US": {
+                    "type": "onap.policies.optimization.resource.AffinityPolicy",
+                    "version": "1.0.0",
+                    "type_version": "1.0.0",
+                    "metadata": {
+                        "policy-id": "OSDF_CASABLANCA.Affinity_Default_US",
+                        "policy-version": 1
+                    },
+                    "properties": {
+                        "scope": [],
+                        "services": [],
+                        "resources": [],
+                        "geography": [
+                            "US"
+                        ],
+                        "identity": "affinity_vCPE",
+                        "applicableResources": "any",
+                        "affinityProperties": {
+                            "qualifier": "same",
+                            "category": "complex"
+                        }
+                    }
+                }
+            },
+            {
+                "OSDF_CASABLANCA.Affinity_Default_vCPE_US_0": {
+                    "type": "onap.policies.optimization.resource.AffinityPolicy",
+                    "version": "1.0.0",
+                    "type_version": "1.0.0",
+                    "metadata": {
+                        "policy-id": "OSDF_CASABLANCA.Affinity_Default_vCPE_US_0",
+                        "policy-version": 1
+                    },
+                    "properties": {
+                        "scope": [],
+                        "services": [
+                            "vCPE"
+                        ],
+                        "resources": [],
+                        "geography": [
+                            "US"
+                        ],
+                        "identity": "affinity_vCPE",
+                        "applicableResources": "any",
+                        "affinityProperties": {
+                            "qualifier": "different",
+                            "category": "complex"
+                        }
+                    }
+                }
+            },
+            {
+                "OSDF_CASABLANCA.Affinity_vCPE_US_Gold_1": {
+                    "type": "onap.policies.optimization.resource.AffinityPolicy",
+                    "version": "1.0.0",
+                    "type_version": "1.0.0",
+                    "metadata": {
+                        "policy-id": "OSDF_CASABLANCA.Affinity_vCPE_1",
+                        "policy-version": 1
+                    },
+                    "properties": {
+                        "scope": [
+                            "gold"
+                        ],
+                        "services": [
+                            "vCPE"
+                        ],
                         "resources": [
                             "vGMuxInfra",
                             "vG"
-                        ]
+                        ],
+                        "geography": [
+                            "US",
+                            "INTERNATIONAL"
+                        ],
+                        "identity": "affinity_vCPE",
+                        "applicableResources": "any",
+                        "affinityProperties": {
+                            "qualifier": "same",
+                            "category": "availabilityZone"
+                        }
+                    }
+                }
+            },
+            {
+                "OSDF_CASABLANCA.Affinity_vCPE_US_Platinum_1": {
+                    "type": "onap.policies.optimization.resource.AffinityPolicy",
+                    "version": "1.0.0",
+                    "type_version": "1.0.0",
+                    "metadata": {
+                        "policy-id": "OSDF_CASABLANCA.Affinity_vCPE_1",
+                        "policy-version": 1
+                    },
+                    "properties": {
+                        "scope": [
+                            "platinum"
+                        ],
+                        "services": [
+                            "vCPE"
+                        ],
+                        "resources": [
+                            "vGMuxInfra",
+                            "vG"
+                        ],
+                        "geography": [
+                            "US",
+                            "INTERNATIONAL"
+                        ],
+                        "identity": "affinity_vCPE",
+                        "applicableResources": "any",
+                        "affinityProperties": {
+                            "qualifier": "different",
+                            "category": "availabilityZone"
+                        }
                     }
                 }
             },
             {
                 "OSDF_CASABLANCA.Capacity_vG_1": {
-                    "type": "onap.policies.optimization.Vim_fit",
+                    "type": "onap.policies.optimization.resource.Vim_fit",
                     "version": "1.0.0",
+                    "type_version": "1.0.0",
                     "metadata": {
-                        "policy-id": "OSDF_CASABLANCA.Capacity_vG_1"
+                        "policy-id": "OSDF_CASABLANCA.Capacity_vG_1",
+                        "policy-version": 1
                     },
                     "properties": {
-                        "identity": "capacity_vG",
-                        "policyScope": [
-                            "VCPE",
-                            "US",
-                            "INTERNATIONAL",
-                            "ip",
-                            "vG"
+                        "scope": [],
+                        "services": [
+                            "vCPE"
                         ],
                         "resources": [
                             "vG"
                         ],
+                        "geography": [
+                            "US",
+                            "INTERNATIONAL"
+                        ],
+                        "identity": "capacity_vG",
+                        "applicableResources": "any",
                         "capacityProperty": {
                             "controller": "multicloud",
                             "request": "{\"vCPU\": 10, \"Memory\": {\"quantity\": {\"get_param\": \"REQUIRED_MEM\"}, \"unit\": \"GB\"}, \"Storage\": {\"quantity\": {\"get_param\": \"REQUIRED_DISK\"}, \"unit\": \"GB\"}}"
-                        },
-                        "policyType": "vim_fit",
-                        "applicableResources": "any"
+                        }
+                    }
+                }
+            },
+            {
+                "OSDF_CASABLANCA.Capacity_vG_2": {
+                    "type": "onap.policies.optimization.resource.Vim_fit",
+                    "version": "1.0.0",
+                    "type_version": "1.0.0",
+                    "metadata": {
+                        "policy-id": "OSDF_CASABLANCA.Capacity_vG_2",
+                        "policy-version": 1
+                    },
+                    "properties": {
+                        "scope": [],
+                        "services": [
+                            "vCPE"
+                        ],
+                        "resources": [
+                            "vG"
+                        ],
+                        "geography": [
+                            "US",
+                            "INTERNATIONAL"
+                        ],
+                        "identity": "capacity_vG",
+                        "applicableResources": "any",
+                        "capacityProperty": {
+                            "controller": "multicloud",
+                            "request": "{\"vCPU\": 15, \"Memory\": {\"quantity\": {\"get_param\": \"REQUIRED_MEM\"}, \"unit\": \"MB\"}, \"Storage\": {\"quantity\": {\"get_param\": \"REQUIRED_DISK\"}, \"unit\": \"GB\"}}"
+                        }
                     }
                 }
             },
             {
                 "OSDF_CASABLANCA.Distance_vG_1": {
-                    "type": "onap.policies.optimization.DistancePolicy",
+                    "type": "onap.policies.optimization.resource.DistancePolicy",
                     "version": "1.0.0",
+                    "type_version": "1.0.0",
                     "metadata": {
-                        "policy-id": "OSDF_CASABLANCA.Distance_vG_1"
+                        "policy-id": "OSDF_CASABLANCA.Distance_vG_1",
+                        "policy-version": 1
                     },
                     "properties": {
+                        "scope": [
+                            "platinum"
+                        ],
+                        "services": [
+                            "vCPE"
+                        ],
+                        "resources": [
+                            "vG"
+                        ],
+                        "geography": [
+                            "US",
+                            "INTERNATIONAL"
+                        ],
+                        "identity": "distance-vG",
+                        "applicableResources": "any",
                         "distanceProperties": {
                             "locationInfo": "customer_loc",
                             "distance": {
@@ -74,54 +235,188 @@
                                 "operator": "<",
                                 "unit": "km"
                             }
-                        },
-                        "identity": "distance-vG",
-                        "resources": [
-                            "vG"
-                        ],
-                        "policyScope": [
-                            "vCPE",
-                            "US",
-                            "INTERNATIONAL",
-                            "ip",
-                            "vG"
-                        ],
-                        "policyType": "distance_to_location",
-                        "applicableResources": "any"
+                        }
+                    }
+                }
+            },
+            {
+                "OSDF_CASABLANCA.hpa_policy_Default": {
+                    "type": "onap.policies.optimization.resource.HpaPolicy",
+                    "version": "1.0.0",
+                    "type_version": "1.0.0",
+                    "metadata": {
+                        "policy-id": "OSDF_CASABLANCA.hpa_policy_Default",
+                        "policy-version": 1
+                    },
+                    "properties": {
+                        "scope": [],
+                        "services": [],
+                        "resources": [],
+                        "geography": [],
+                        "identity": "hpa-vG",
+                        "flavorFeatures": [
+                            {
+                                "id": "vg_1",
+                                "type": "vnfc",
+                                "directives": [
+                                    {
+                                        "type": "flavor_directives",
+                                        "attributes": [
+                                            {
+                                                "attribute_name": "flavor_label_vm_01",
+                                                "attribute_value": ""
+                                            }
+                                        ]
+                                    }
+                                ],
+                                "flavorProperties": [
+                                    {
+                                        "hpa-feature": "basicCapabilities",
+                                        "mandatory": true,
+                                        "architecture": "generic",
+                                        "directives": [],
+                                        "hpa-feature-attributes": [
+                                            {
+                                                "hpa-attribute-key": "numVirtualCpu",
+                                                "hpa-attribute-value": 8,
+                                                "operator": [
+                                                    ">="
+                                                ],
+                                                "unit": ""
+                                            },
+                                            {
+                                                "hpa-attribute-key": "virtualMemSize",
+                                                "hpa-attribute-value": 6,
+                                                "operator": [
+                                                    "<="
+                                                ],
+                                                "unit": ""
+                                            }
+                                        ]
+                                    },
+                                    {
+                                        "hpa-feature": "ovsDpdk",
+                                        "mandatory": false,
+                                        "architecture": "generic",
+                                        "directives": [],
+                                        "hpa-feature-attributes": [
+                                            {
+                                                "hpa-attribute-key": "dataProcessingAccelerationLibrary",
+                                                "hpa-attribute-value": "ovsDpdk_version",
+                                                "operator": [
+                                                    "="
+                                                ],
+                                                "unit": ""
+                                            }
+                                        ]
+                                    }
+                                ]
+                            }
+                        ]
                     }
                 }
             },
             {
                 "OSDF_CASABLANCA.hpa_policy_vG_1": {
-                    "type": "onap.policies.optimization.HpaPolicy",
+                    "type": "onap.policies.optimization.resource.HpaPolicy",
                     "version": "1.0.0",
+                    "type_version": "1.0.0",
                     "metadata": {
-                        "policy-id": "OSDF_CASABLANCA.hpa_policy_vG_1"
+                        "policy-id": "OSDF_CASABLANCA.hpa_policy_vG_1",
+                        "policy-version": 1
                     },
                     "properties": {
+                        "scope": [],
+                        "services": [
+                            "vCPE",
+                            "vOtherService"
+                        ],
                         "resources": [
                             "vG"
                         ],
+                        "geography": [],
                         "identity": "hpa-vG",
-                        "policyScope": [
-                            "vCPE",
-                            "US",
-                            "INTERNATIONAL",
-                            "ip",
-                            "vG"
-                        ],
-                        "policyType": "hpa"
+                        "flavorFeatures": [
+                            {
+                                "id": "vg_1",
+                                "type": "vnfc",
+                                "directives": [
+                                    {
+                                        "type": "flavor_directives",
+                                        "attributes": [
+                                            {
+                                                "attribute_name": "flavor_label_vm_01",
+                                                "attribute_value": ""
+                                            }
+                                        ]
+                                    }
+                                ],
+                                "flavorProperties": [
+                                    {
+                                        "hpa-feature": "basicCapabilities",
+                                        "mandatory": true,
+                                        "architecture": "generic",
+                                        "directives": [],
+                                        "hpa-feature-attributes": [
+                                            {
+                                                "hpa-attribute-key": "numVirtualCpu",
+                                                "hpa-attribute-value": 6,
+                                                "operator": [
+                                                    ">="
+                                                ],
+                                                "unit": ""
+                                            },
+                                            {
+                                                "hpa-attribute-key": "virtualMemSize",
+                                                "hpa-attribute-value": 4,
+                                                "operator": [
+                                                    "<="
+                                                ],
+                                                "unit": ""
+                                            }
+                                        ]
+                                    },
+                                    {
+                                        "hpa-feature": "ovsDpdk",
+                                        "mandatory": false,
+                                        "architecture": "generic",
+                                        "directives": [],
+                                        "hpa-feature-attributes": [
+                                            {
+                                                "hpa-attribute-key": "dataProcessingAccelerationLibrary",
+                                                "hpa-attribute-value": "ovsDpdk_version",
+                                                "operator": [
+                                                    "="
+                                                ],
+                                                "unit": ""
+                                            }
+                                        ]
+                                    }
+                                ]
+                            }
+                        ]
                     }
                 }
             },
             {
                 "OSDF_CASABLANCA.queryPolicy_vCPE": {
-                    "type": "onap.policies.optimization.QueryPolicy",
+                    "type": "onap.policies.optimization.service.QueryPolicy",
                     "version": "1.0.0",
+                    "type_version": "1.0.0",
                     "metadata": {
-                        "policy-id": "OSDF_CASABLANCA.queryPolicy_vCPE"
+                        "policy-id": "OSDF_CASABLANCA.queryPolicy_vCPE",
+                        "policy-version": 1
                     },
                     "properties": {
+                        "scope": [],
+                        "services": [
+                            "vCPE"
+                        ],
+                        "geography": [
+                            "US",
+                            "INTERNATIONAL"
+                        ],
+                        "identity": "vCPE_Query_Policy",
                         "queryProperties": [
                             {
                                 "attribute": "locationId",
@@ -148,82 +443,99 @@
                                 "attribute_location": "customerLongitude",
                                 "value": 2.2
                             }
-                        ],
-                        "serviceName": "vCPE",
-                        "policyScope": [
-                            "vCPE",
-                            "US",
-                            "INTERNATIONAL",
-                            "ip",
-                            "vGMuxInfra",
-                            "vG"
-                        ],
-                        "policyType": "request_param_query",
-                        "identity": "vCPE_Query_Policy"
+                        ]
                     }
                 }
             },
             {
                 "OSDF_CASABLANCA.SubscriberPolicy_v1": {
-                    "type": "onap.policies.optimization.SubscriberPolicy",
+                    "type": "onap.policies.optimization.service.SubscriberPolicy",
                     "version": "1.0.0",
+                    "type_version": "1.0.0",
                     "metadata": {
-                        "policy-id": "OSDF_CASABLANCA.SubscriberPolicy_v1"
+                        "policy-id": "OSDF_CASABLANCA.SubscriberPolicy_v1",
+                        "policy-version": 1
                     },
                     "properties": {
-                        "identity": "subscriber_vCPE",
-                        "policyScope": [
-                            "vCPE",
-                            "subscriber_x",
-                            "subscriber_y",
-                            "subscriberPolicy"
+                        "scope": [],
+                        "services": [
+                            "vCPE"
                         ],
-                        "properties": {
+                        "identity": "subscriber_vCPE",
+                        "subscriberProperties": {
                             "subscriberName": [
                                 "subscriber_x",
                                 "subscriber_y"
                             ],
                             "subscriberRole": [
-                                "PVT Homing"
+                                "platinum"
                             ],
                             "provStatus": [
                                 "CAPPED"
                             ]
-                        },
-                        "policyType": "subscriberPolicy",
-                        "serviceName": "vCPE"
+                        }
+                    }
+                }
+            },
+            {
+                "OSDF_CASABLANCA.SubscriberPolicy_v2": {
+                    "type": "onap.policies.optimization.service.SubscriberPolicy",
+                    "version": "1.0.0",
+                    "type_version": "1.0.0",
+                    "metadata": {
+                        "policy-id": "OSDF_CASABLANCA.SubscriberPolicy_v2",
+                        "policy-version": 1
+                    },
+                    "properties": {
+                        "scope": [],
+                        "services": [
+                            "vCPE"
+                        ],
+                        "identity": "subscriber_vCPE",
+                        "subscriberProperties": {
+                            "subscriberName": [
+                                "subscriber_a",
+                                "subscriber_b"
+                            ],
+                            "subscriberRole": [
+                                "gold"
+                            ],
+                            "provStatus": [
+                                "CAPPED"
+                            ]
+                        }
                     }
                 }
             },
             {
                 "OSDF_CASABLANCA.vnfPolicy_vG": {
-                    "type": "onap.policies.optimization.VnfPolicy",
+                    "type": "onap.policies.optimization.resource.VnfPolicy",
                     "version": "1.0.0",
+                    "type_version": "1.0.0",
                     "metadata": {
-                        "policy-id": "OSDF_CASABLANCA.vnfPolicy_vG"
+                        "policy-id": "OSDF_CASABLANCA.vnfPolicy_vG",
+                        "policy-version": 1
                     },
                     "properties": {
-                        "identity": "vnf_vG",
-                        "policyScope": [
-                            "vCPE",
-                            "US",
-                            "INTERNATIONAL",
-                            "ip",
-                            "vG"
+                        "scope": [],
+                        "services": [
+                            "vCPE"
                         ],
-                        "policyType": "vnfPolicy",
                         "resources": [
                             "vG"
                         ],
+                        "geography": [
+                            "US",
+                            "INTERNATIONAL"
+                        ],
+                        "identity": "vnf_vG",
                         "applicableResources": "any",
                         "vnfProperties": [
                             {
                                 "inventoryProvider": "aai",
                                 "serviceType": "",
-                                "inventoryType": "cloud",
-                                "customerId": "",
-                                "orchestrationStatus": "",
-                                "equipmentRole": ""
+                                "inventoryType": "cloudRegionId",
+                                "customerId": ""
                             }
                         ]
                     }
diff --git a/models-examples/src/main/resources/policies/vCPE.policies.optimization.input.tosca.yaml b/models-examples/src/main/resources/policies/vCPE.policies.optimization.input.tosca.yaml
index 6e32cca..fb84863 100644
--- a/models-examples/src/main/resources/policies/vCPE.policies.optimization.input.tosca.yaml
+++ b/models-examples/src/main/resources/policies/vCPE.policies.optimization.input.tosca.yaml
@@ -1,86 +1,277 @@
 tosca_definitions_version: tosca_simple_yaml_1_0_0
 topology_template:
   policies:
-    - 
-        OSDF_CASABLANCA.Affinity_vCPE_1:
-            type: onap.policies.optimization.AffinityPolicy
+    -
+        OSDF_CASABLANCA.Affinity_Default:
+            type: onap.policies.optimization.resource.AffinityPolicy
             version: 1.0.0
+            type_version: 1.0.0
             metadata:
-                policy-id: OSDF_CASABLANCA.Affinity_vCPE_1
+                policy-id: OSDF_CASABLANCA.Affinity_Default
+                policy-version: 1
             properties:
+                scope: []
+                services: []
+                resources: []
+                geography: []
                 identity: affinity_vCPE
-                policyScope: [vCPE, US, INTERNATIONAL, ip, vGMuxInfra, vG]
-                affinityProperties: 
+                applicableResources: any
+                affinityProperties:
                     qualifier: same
                     category: complex
-                policyType: zone
+    -
+        OSDF_CASABLANCA.Affinity_Default_US:
+            type: onap.policies.optimization.resource.AffinityPolicy
+            version: 1.0.0
+            type_version: 1.0.0
+            metadata:
+                policy-id: OSDF_CASABLANCA.Affinity_Default_US
+                policy-version: 1
+            properties:
+                scope: []
+                services: []
+                resources: []
+                geography: [US]
+                identity: affinity_vCPE
+                applicableResources: any
+                affinityProperties:
+                    qualifier: same
+                    category: complex
+    -
+        OSDF_CASABLANCA.Affinity_Default_vCPE_US_0:
+            type: onap.policies.optimization.resource.AffinityPolicy
+            version: 1.0.0
+            type_version: 1.0.0
+            metadata:
+                policy-id: OSDF_CASABLANCA.Affinity_Default_vCPE_US_0
+                policy-version: 1
+            properties:
+                scope: []
+                services: [vCPE]
+                resources: []
+                geography: [US]
+                identity: affinity_vCPE
+                applicableResources: any
+                affinityProperties:
+                    qualifier: different
+                    category: complex
+    -
+        OSDF_CASABLANCA.Affinity_vCPE_US_Gold_1:
+            type: onap.policies.optimization.resource.AffinityPolicy
+            version: 1.0.0
+            type_version: 1.0.0
+            metadata:
+                policy-id: OSDF_CASABLANCA.Affinity_vCPE_1
+                policy-version: 1
+            properties:
+                scope: [gold]
+                services: [vCPE]
                 resources: [vGMuxInfra, vG]
+                geography: [US, INTERNATIONAL]
+                identity: affinity_vCPE
+                applicableResources: any
+                affinityProperties:
+                    qualifier: same
+                    category: availabilityZone
+    -
+        OSDF_CASABLANCA.Affinity_vCPE_US_Platinum_1:
+            type: onap.policies.optimization.resource.AffinityPolicy
+            version: 1.0.0
+            type_version: 1.0.0
+            metadata:
+                policy-id: OSDF_CASABLANCA.Affinity_vCPE_1
+                policy-version: 1
+            properties:
+                scope: [platinum]
+                services: [vCPE]
+                resources: [vGMuxInfra, vG]
+                geography: [US, INTERNATIONAL]
+                identity: affinity_vCPE
+                applicableResources: any
+                affinityProperties:
+                    qualifier: different
+                    category: availabilityZone
     -
         OSDF_CASABLANCA.Capacity_vG_1:
-            type: onap.policies.optimization.Vim_fit
+            type: onap.policies.optimization.resource.Vim_fit
             version: 1.0.0
+            type_version: 1.0.0
             metadata:
                 policy-id: OSDF_CASABLANCA.Capacity_vG_1
+                policy-version: 1
             properties:
-                identity: capacity_vG
-                policyScope: [VCPE, US, INTERNATIONAL, ip, vG]
+                scope: []
+                services: [vCPE]
                 resources: [vG]
-                capacityProperty: 
+                geography: [US, INTERNATIONAL]
+                identity: capacity_vG
+                applicableResources: any
+                capacityProperty:
                    controller: multicloud
                    request: "{\"vCPU\": 10, \"Memory\": {\"quantity\": {\"get_param\": \"REQUIRED_MEM\"}, \"unit\": \"GB\"}, \"Storage\": {\"quantity\": {\"get_param\": \"REQUIRED_DISK\"}, \"unit\": \"GB\"}}"
-                policyType: vim_fit
+    -
+        OSDF_CASABLANCA.Capacity_vG_2:
+            type: onap.policies.optimization.resource.Vim_fit
+            version: 1.0.0
+            type_version: 1.0.0
+            metadata:
+                policy-id: OSDF_CASABLANCA.Capacity_vG_2
+                policy-version: 1
+            properties:
+                scope: []
+                services: [vCPE]
+                resources: [vG]
+                geography: [US, INTERNATIONAL]
+                identity: capacity_vG
                 applicableResources: any
+                capacityProperty:
+                   controller: multicloud
+                   request: "{\"vCPU\": 15, \"Memory\": {\"quantity\": {\"get_param\": \"REQUIRED_MEM\"}, \"unit\": \"MB\"}, \"Storage\": {\"quantity\": {\"get_param\": \"REQUIRED_DISK\"}, \"unit\": \"GB\"}}"
     -
         OSDF_CASABLANCA.Distance_vG_1:
-            type: onap.policies.optimization.DistancePolicy
+            type: onap.policies.optimization.resource.DistancePolicy
             version: 1.0.0
+            type_version: 1.0.0
             metadata:
                 policy-id: OSDF_CASABLANCA.Distance_vG_1
+                policy-version: 1
             properties:
-                distanceProperties: 
+                scope: [platinum]
+                services: [vCPE]
+                resources: [vG]
+                geography: [US, INTERNATIONAL]
+                identity: distance-vG
+                applicableResources: any
+                distanceProperties:
                     locationInfo: customer_loc
-                    distance: 
+                    distance:
                         value: 1500
                         operator: "<"
                         unit: km
-                identity: "distance-vG"
-                resources: [vG]
-                policyScope: [vCPE, US, INTERNATIONAL, ip, vG]
-                policyType: distance_to_location
-                applicableResources: any
+    -
+        OSDF_CASABLANCA.hpa_policy_Default:
+            type: onap.policies.optimization.resource.HpaPolicy
+            version: 1.0.0
+            type_version: 1.0.0
+            metadata:
+                policy-id: OSDF_CASABLANCA.hpa_policy_Default
+                policy-version: 1
+            properties:
+                scope: []
+                services: []
+                resources: []
+                geography: []
+                identity: hpa-vG
+                flavorFeatures:
+                    -
+                         id: vg_1
+                         type: vnfc
+                         directives:
+                             -    type: flavor_directives
+                                  attributes:
+                                      -    attribute_name: flavor_label_vm_01
+                                           attribute_value: ""
+                         flavorProperties:
+                             -
+                                  hpa-feature: basicCapabilities
+                                  mandatory: True
+                                  architecture: generic
+                                  directives: []
+                                  hpa-feature-attributes:
+                                      -    hpa-attribute-key: numVirtualCpu
+                                           hpa-attribute-value: 8
+                                           operator: ['>=']
+                                           unit: ""
+                                      -    hpa-attribute-key: virtualMemSize
+                                           hpa-attribute-value: 6
+                                           operator: ['<=']
+                                           unit: ""
+                             -
+                                  hpa-feature: ovsDpdk
+                                  mandatory: False
+                                  architecture: generic
+                                  directives: []
+                                  hpa-feature-attributes:
+                                      -    hpa-attribute-key: dataProcessingAccelerationLibrary
+                                           hpa-attribute-value: ovsDpdk_version
+                                           operator: [=]
+                                           unit: ""
     -
         OSDF_CASABLANCA.hpa_policy_vG_1:
-            type: onap.policies.optimization.HpaPolicy
+            type: onap.policies.optimization.resource.HpaPolicy
             version: 1.0.0
+            type_version: 1.0.0
             metadata:
                 policy-id: OSDF_CASABLANCA.hpa_policy_vG_1
+                policy-version: 1
             properties:
+                scope: []
+                services: [vCPE, vOtherService]
                 resources: [vG]
-                identity: "hpa-vG"
-                policyScope: [vCPE, US, INTERNATIONAL, ip, vG]
-                policyType: hpa            
-                # NONE OF THE FLAVORFEATURES CAME OUT RIGHT
+                geography: []
+                identity: hpa-vG
+                flavorFeatures:
+                    -
+                         id: vg_1
+                         type: vnfc
+                         directives:
+                             -    type: flavor_directives
+                                  attributes:
+                                      -    attribute_name: flavor_label_vm_01
+                                           attribute_value: ""
+                         flavorProperties:
+                             -
+                                  hpa-feature: basicCapabilities
+                                  mandatory: True
+                                  architecture: generic
+                                  directives: []
+                                  hpa-feature-attributes:
+                                      -    hpa-attribute-key: numVirtualCpu
+                                           hpa-attribute-value: 6
+                                           operator: ['>=']
+                                           unit: ""
+                                      -    hpa-attribute-key: virtualMemSize
+                                           hpa-attribute-value: 4
+                                           operator: ['<=']
+                                           unit: ""
+                             -
+                                  hpa-feature: ovsDpdk
+                                  mandatory: False
+                                  architecture: generic
+                                  directives: []
+                                  hpa-feature-attributes:
+                                      -    hpa-attribute-key: dataProcessingAccelerationLibrary
+                                           hpa-attribute-value: ovsDpdk_version
+                                           operator: [=]
+                                           unit: ""
     -
         OSDF_CASABLANCA.queryPolicy_vCPE:
-            type: onap.policies.optimization.QueryPolicy
+            type: onap.policies.optimization.service.QueryPolicy
             version: 1.0.0
+            type_version: 1.0.0
             metadata:
                 policy-id: OSDF_CASABLANCA.queryPolicy_vCPE
+                policy-version: 1
             properties:
-                queryProperties: 
-                    - 
+                scope: []
+                services: [vCPE]
+#                resources: [vGMuxInfra, vG]
+                geography: [US, INTERNATIONAL]
+                identity: vCPE_Query_Policy
+                queryProperties:
+                    -
                         attribute: locationId
                         attribute_location: customerLocation
                         value: ""
-                    - 
+                    -
                         attribute: id
                         attribute_location: "vpnInfo.vpnId"
                         value: ""
-                    - 
+                    -
                         attribute: upstreamBW
                         attribute_location: "vpnInfo.upstreamBW"
                         value: ""
-                    - 
+                    -
                         attribute: customerLatitude
                         attribute_location: customerLatitude
                         value: 1.1
@@ -88,43 +279,56 @@
                         attribute: customerLongitude
                         attribute_location: customerLongitude
                         value: 2.2
-                serviceName: vCPE
-                policyScope: [vCPE, US, INTERNATIONAL, ip, vGMuxInfra, vG]
-                policyType: request_param_query
-                identity: vCPE_Query_Policy            
-            
     -
         OSDF_CASABLANCA.SubscriberPolicy_v1:
-            type: onap.policies.optimization.SubscriberPolicy
+            type: onap.policies.optimization.service.SubscriberPolicy
             version: 1.0.0
+            type_version: 1.0.0
             metadata:
                 policy-id: OSDF_CASABLANCA.SubscriberPolicy_v1
+                policy-version: 1
             properties:
+                scope: []
+                services: [vCPE]
                 identity: subscriber_vCPE
-                policyScope: [vCPE, subscriber_x, subscriber_y, subscriberPolicy]
-                properties: 
+                subscriberProperties:
                     subscriberName: [subscriber_x, subscriber_y]
-                    subscriberRole: ["PVT Homing"]
+                    subscriberRole: [platinum]
                     provStatus: [CAPPED]
-                policyType: subscriberPolicy
-                serviceName: vCPE
+    -
+        OSDF_CASABLANCA.SubscriberPolicy_v2:
+            type: onap.policies.optimization.service.SubscriberPolicy
+            version: 1.0.0
+            type_version: 1.0.0
+            metadata:
+                policy-id: OSDF_CASABLANCA.SubscriberPolicy_v2
+                policy-version: 1
+            properties:
+                scope: []
+                services: [vCPE]
+                identity: subscriber_vCPE
+                subscriberProperties:
+                    subscriberName: [subscriber_a, subscriber_b]
+                    subscriberRole: [gold]
+                    provStatus: [CAPPED]
     -
         OSDF_CASABLANCA.vnfPolicy_vG:
-            type: onap.policies.optimization.VnfPolicy
+            type: onap.policies.optimization.resource.VnfPolicy
             version: 1.0.0
+            type_version: 1.0.0
             metadata:
                 policy-id: OSDF_CASABLANCA.vnfPolicy_vG
+                policy-version: 1
             properties:
-                identity: vnf_vG
-                policyScope: [vCPE, US, INTERNATIONAL, ip, vG]
-                policyType: vnfPolicy
+                scope: []
+                services: [vCPE]
                 resources: [vG]
+                geography: [US, INTERNATIONAL]
+                identity: vnf_vG
                 applicableResources: any
-                vnfProperties: 
-                    - 
+                vnfProperties:
+                    -
                         inventoryProvider: aai
                         serviceType: ""
-                        inventoryType: cloud
+                        inventoryType: cloudRegionId
                         customerId: ""
-                        orchestrationStatus: ""
-                        equipmentRole: ""
\ No newline at end of file
diff --git a/models-examples/src/main/resources/policytypes/onap.policies.Optimization.yaml b/models-examples/src/main/resources/policytypes/onap.policies.Optimization.yaml
index f88239d..2cd391f 100644
--- a/models-examples/src/main/resources/policytypes/onap.policies.Optimization.yaml
+++ b/models-examples/src/main/resources/policytypes/onap.policies.Optimization.yaml
@@ -13,22 +13,6 @@
             required: true
             entry_schema:
                type: string
-         services:
-            description: One or more services that the policy applies to.
-            type: list
-            metadata:
-               matchable: true
-            required: true
-            entry_schema:
-               type: string
-         resources:
-            description: One or more VNF resources that the policy applies to.
-            type: list
-            metadata:
-               matchable: true
-            required: true
-            entry_schema:
-               type: string
          geography:
             description: One or more geographic regions
             type: list
diff --git a/models-examples/src/main/resources/policytypes/onap.policies.optimization.Resource.yaml b/models-examples/src/main/resources/policytypes/onap.policies.optimization.Resource.yaml
new file mode 100644
index 0000000..1d81351
--- /dev/null
+++ b/models-examples/src/main/resources/policytypes/onap.policies.optimization.Resource.yaml
@@ -0,0 +1,23 @@
+tosca_definitions_version: tosca_simple_yaml_1_0_0
+policy_types:
+   onap.policies.optimization.Resource:
+      derived_from: onap.policies.Optimization
+      version: 1.0.0
+      description: The base policy type for all policies that govern optimization for a Resource in a Service.
+      properties:
+         services:
+            description: One or more services that the policy applies to.
+            type: list
+            metadata:
+               matchable: true
+            required: true
+            entry_schema:
+               type: string
+         resources:
+            description: One or more VNF resources that the policy applies to.
+            type: list
+            metadata:
+               matchable: true
+            required: true
+            entry_schema:
+               type: string
\ No newline at end of file
diff --git a/models-examples/src/main/resources/policytypes/onap.policies.optimization.Service.yaml b/models-examples/src/main/resources/policytypes/onap.policies.optimization.Service.yaml
new file mode 100644
index 0000000..8e7b724
--- /dev/null
+++ b/models-examples/src/main/resources/policytypes/onap.policies.optimization.Service.yaml
@@ -0,0 +1,15 @@
+tosca_definitions_version: tosca_simple_yaml_1_0_0
+policy_types:
+   onap.policies.optimization.Service:
+      derived_from: onap.policies.Optimization
+      version: 1.0.0
+      description: The base policy type for all policies that govern optimization for a Service.
+      properties:
+         services:
+            description: One or more services that the policy applies to.
+            type: list
+            metadata:
+               matchable: true
+            required: true
+            entry_schema:
+               type: string               
\ No newline at end of file
diff --git a/models-examples/src/main/resources/policytypes/onap.policies.optimization.AffinityPolicy.yaml b/models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.AffinityPolicy.yaml
similarity index 87%
rename from models-examples/src/main/resources/policytypes/onap.policies.optimization.AffinityPolicy.yaml
rename to models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.AffinityPolicy.yaml
index abac219..173691f 100644
--- a/models-examples/src/main/resources/policytypes/onap.policies.optimization.AffinityPolicy.yaml
+++ b/models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.AffinityPolicy.yaml
@@ -1,7 +1,7 @@
 tosca_definitions_version: tosca_simple_yaml_1_0_0
 policy_types:
-   onap.policies.optimization.AffinityPolicy:
-      derived_from: onap.policies.Optimization
+   onap.policies.optimization.resource.AffinityPolicy:
+      derived_from: onap.policies.optimization.Resource
       version: 1.0.0
       properties:
          applicableResources:
diff --git a/models-examples/src/main/resources/policytypes/onap.policies.optimization.DistancePolicy.yaml b/models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.DistancePolicy.yaml
similarity index 92%
rename from models-examples/src/main/resources/policytypes/onap.policies.optimization.DistancePolicy.yaml
rename to models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.DistancePolicy.yaml
index 3c9150d..060c4f9 100644
--- a/models-examples/src/main/resources/policytypes/onap.policies.optimization.DistancePolicy.yaml
+++ b/models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.DistancePolicy.yaml
@@ -1,7 +1,7 @@
 tosca_definitions_version: tosca_simple_yaml_1_0_0
 policy_types:
-   onap.policies.optimization.DistancePolicy:
-      derived_from: onap.policies.Optimization
+   onap.policies.optimization.resource.DistancePolicy:
+      derived_from: onap.policies.optimization.Resource
       version: 1.0.0
       properties:
          applicableResources:
diff --git a/models-examples/src/main/resources/policytypes/onap.policies.optimization.HpaPolicy.yaml b/models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.HpaPolicy.yaml
similarity index 96%
rename from models-examples/src/main/resources/policytypes/onap.policies.optimization.HpaPolicy.yaml
rename to models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.HpaPolicy.yaml
index dbb5e9e..d35552f 100644
--- a/models-examples/src/main/resources/policytypes/onap.policies.optimization.HpaPolicy.yaml
+++ b/models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.HpaPolicy.yaml
@@ -1,7 +1,7 @@
 tosca_definitions_version: tosca_simple_yaml_1_0_0
 policy_types:
-   onap.policies.optimization.HpaPolicy:
-      derived_from: onap.policies.Optimization
+   onap.policies.optimization.resource.HpaPolicy:
+      derived_from: onap.policies.optimization.Resource
       version: 1.0.0
       properties:
          flavorFeatures:
diff --git a/models-examples/src/main/resources/policytypes/onap.policies.optimization.OptimizationPolicy.yaml b/models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.OptimizationPolicy.yaml
similarity index 93%
rename from models-examples/src/main/resources/policytypes/onap.policies.optimization.OptimizationPolicy.yaml
rename to models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.OptimizationPolicy.yaml
index e03ceee..abc329c 100644
--- a/models-examples/src/main/resources/policytypes/onap.policies.optimization.OptimizationPolicy.yaml
+++ b/models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.OptimizationPolicy.yaml
@@ -1,7 +1,7 @@
 tosca_definitions_version: tosca_simple_yaml_1_0_0
 policy_types:
-   onap.policies.optimization.OptimizationPolicy:
-      derived_from: onap.policies.Optimization
+   onap.policies.optimization.resource.OptimizationPolicy:
+      derived_from: onap.policies.optimization.Resource
       version: 1.0.0
       properties:
          objective:
diff --git a/models-examples/src/main/resources/policytypes/onap.policies.optimization.PciPolicy.yaml b/models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.PciPolicy.yaml
similarity index 88%
rename from models-examples/src/main/resources/policytypes/onap.policies.optimization.PciPolicy.yaml
rename to models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.PciPolicy.yaml
index 097a5f1..887e372 100644
--- a/models-examples/src/main/resources/policytypes/onap.policies.optimization.PciPolicy.yaml
+++ b/models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.PciPolicy.yaml
@@ -1,7 +1,7 @@
 tosca_definitions_version: tosca_simple_yaml_1_0_0
 policy_types:
-   onap.policies.optimization.PciPolicy:
-      derived_from: onap.policies.Optimization
+   onap.policies.optimization.resource.PciPolicy:
+      derived_from: onap.policies.optimization.Resource
       version: 1.0.0
       properties:
          pciProperties:
diff --git a/models-examples/src/main/resources/policytypes/onap.policies.optimization.Vim_fit.yaml b/models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.Vim_fit.yaml
similarity index 87%
rename from models-examples/src/main/resources/policytypes/onap.policies.optimization.Vim_fit.yaml
rename to models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.Vim_fit.yaml
index b70dddb..fd85124 100644
--- a/models-examples/src/main/resources/policytypes/onap.policies.optimization.Vim_fit.yaml
+++ b/models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.Vim_fit.yaml
@@ -1,7 +1,7 @@
 tosca_definitions_version: tosca_simple_yaml_1_0_0
 policy_types:
-   onap.policies.optimization.Vim_fit:
-      derived_from: onap.policies.Optimization
+   onap.policies.optimization.resource.Vim_fit:
+      derived_from: onap.policies.optimization.Resource
       version: 1.0.0
       properties:
          applicableResources:
diff --git a/models-examples/src/main/resources/policytypes/onap.policies.optimization.VnfPolicy.yaml b/models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.VnfPolicy.yaml
similarity index 91%
rename from models-examples/src/main/resources/policytypes/onap.policies.optimization.VnfPolicy.yaml
rename to models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.VnfPolicy.yaml
index 18a0ccf..960ee15 100644
--- a/models-examples/src/main/resources/policytypes/onap.policies.optimization.VnfPolicy.yaml
+++ b/models-examples/src/main/resources/policytypes/onap.policies.optimization.resource.VnfPolicy.yaml
@@ -1,7 +1,7 @@
 tosca_definitions_version: tosca_simple_yaml_1_0_0
 policy_types:
-   onap.policies.optimization.VnfPolicy:
-      derived_from: onap.policies.Optimization
+   onap.policies.optimization.resource.VnfPolicy:
+      derived_from: onap.policies.optimization.Resource
       version: 1.0.0
       properties:
          applicableResources:
diff --git a/models-examples/src/main/resources/policytypes/onap.policies.optimization.QueryPolicy.yaml b/models-examples/src/main/resources/policytypes/onap.policies.optimization.service.QueryPolicy.yaml
similarity index 84%
rename from models-examples/src/main/resources/policytypes/onap.policies.optimization.QueryPolicy.yaml
rename to models-examples/src/main/resources/policytypes/onap.policies.optimization.service.QueryPolicy.yaml
index 41b923a..68c6636 100644
--- a/models-examples/src/main/resources/policytypes/onap.policies.optimization.QueryPolicy.yaml
+++ b/models-examples/src/main/resources/policytypes/onap.policies.optimization.service.QueryPolicy.yaml
@@ -1,7 +1,7 @@
 tosca_definitions_version: tosca_simple_yaml_1_0_0
 policy_types:
-   onap.policies.optimization.QueryPolicy:
-      derived_from: onap.policies.Optimization
+   onap.policies.optimization.service.QueryPolicy:
+      derived_from: onap.policies.optimization.Service
       version: 1.0.0
       properties:
          queryProperties:
diff --git a/models-examples/src/main/resources/policytypes/onap.policies.optimization.SubscriberPolicy.yaml b/models-examples/src/main/resources/policytypes/onap.policies.optimization.service.SubscriberPolicy.yaml
similarity index 86%
rename from models-examples/src/main/resources/policytypes/onap.policies.optimization.SubscriberPolicy.yaml
rename to models-examples/src/main/resources/policytypes/onap.policies.optimization.service.SubscriberPolicy.yaml
index 010a153..b6327c8 100644
--- a/models-examples/src/main/resources/policytypes/onap.policies.optimization.SubscriberPolicy.yaml
+++ b/models-examples/src/main/resources/policytypes/onap.policies.optimization.service.SubscriberPolicy.yaml
@@ -1,7 +1,7 @@
 tosca_definitions_version: tosca_simple_yaml_1_0_0
 policy_types:
-   onap.policies.optimization.SubscriberPolicy:
-      derived_from: onap.policies.Optimization
+   onap.policies.optimization.service.SubscriberPolicy:
+      derived_from: onap.policies.optimization.Service
       version: 1.0.0
       properties:
          subscriberProperties:
diff --git a/models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/DeploymentGroup.java b/models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/DeploymentGroup.java
new file mode 100644
index 0000000..d98f6ed
--- /dev/null
+++ b/models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/DeploymentGroup.java
@@ -0,0 +1,116 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 AT&T Intellectual Property.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.pdp.concepts;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.NonNull;
+import org.onap.policy.common.parameters.BeanValidationResult;
+import org.onap.policy.common.parameters.ObjectValidationResult;
+import org.onap.policy.common.parameters.ValidationResult;
+import org.onap.policy.common.parameters.ValidationStatus;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.pdp.concepts.DeploymentSubGroup.Action;
+
+/**
+ * Batch modification of a deployment group, which groups multiple DeploymentSubGroup
+ * entities together for a particular domain.
+ */
+@Data
+@NoArgsConstructor
+public class DeploymentGroup {
+    private static final String SUBGROUP_FIELD = "deploymentSubgroups";
+
+    private String name;
+    private List<DeploymentSubGroup> deploymentSubgroups;
+
+    /**
+     * Constructs the object, making a deep copy from the source.
+     *
+     * @param source source from which to copy fields
+     */
+    public DeploymentGroup(@NonNull DeploymentGroup source) {
+        this.name = source.name;
+        this.deploymentSubgroups =
+                        PfUtils.mapList(source.deploymentSubgroups, DeploymentSubGroup::new, new ArrayList<>(0));
+    }
+
+    /**
+     * Validates that appropriate fields are populated for an incoming call to the PAP
+     * REST API.
+     *
+     * @return the validation result
+     */
+    public ValidationResult validatePapRest() {
+        BeanValidationResult result = new BeanValidationResult("group", this);
+
+        result.validateNotNull("name", name);
+        result.validateNotNullList(SUBGROUP_FIELD, deploymentSubgroups, DeploymentSubGroup::validatePapRest);
+
+        if (deploymentSubgroups != null && deploymentSubgroups.isEmpty()) {
+            result.addResult(new ObjectValidationResult(SUBGROUP_FIELD, deploymentSubgroups, ValidationStatus.INVALID,
+                            "is empty"));
+        }
+
+        checkDuplicateSubgroups(result);
+
+        return result;
+    }
+
+    /**
+     * Checks for duplicate subgroups.
+     *
+     * @param result where to place validation results
+     */
+    private void checkDuplicateSubgroups(BeanValidationResult result) {
+        if (deploymentSubgroups == null || !result.isValid()) {
+            return;
+        }
+
+        /*
+         * Verify that if a subgroup appears more than once, then the second appearance is
+         * not a PATCH, as that would overwrite anything that has appeared before.
+         */
+        Map<String, Action> pdpType2action = new HashMap<>();
+
+        for (DeploymentSubGroup subgrp : deploymentSubgroups) {
+            Action action = subgrp.getAction();
+
+            pdpType2action.compute(subgrp.getPdpType(), (pdpType, curact) -> {
+
+                if (curact != null && action == Action.PATCH) {
+                    BeanValidationResult subResult = new BeanValidationResult(pdpType, pdpType);
+                    subResult.addResult(new ObjectValidationResult("action", action, ValidationStatus.INVALID,
+                                    "incompatible with previous action: " + curact));
+                    BeanValidationResult subResult2 = new BeanValidationResult(SUBGROUP_FIELD, subgrp);
+                    subResult2.addResult(subResult);
+                    result.addResult(subResult2);
+                }
+
+                return action;
+            });
+        }
+    }
+}
diff --git a/models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/DeploymentGroups.java b/models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/DeploymentGroups.java
new file mode 100644
index 0000000..0d810d2
--- /dev/null
+++ b/models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/DeploymentGroups.java
@@ -0,0 +1,73 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Models
+ * ================================================================================
+ * Copyright (C) 2019 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.models.pdp.concepts;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import org.onap.policy.common.parameters.BeanValidationResult;
+import org.onap.policy.common.parameters.ObjectValidationResult;
+import org.onap.policy.common.parameters.ValidationResult;
+import org.onap.policy.common.parameters.ValidationStatus;
+
+/**
+ * Batch modification of a deployment groups via the PDP Group deployment REST API.
+ */
+@Getter
+@Setter
+@ToString
+public class DeploymentGroups {
+    private static final String GROUPS_FIELD = "groups";
+
+    private List<DeploymentGroup> groups;
+
+    /**
+     * Validates that appropriate fields are populated for an incoming call to the PAP
+     * REST API.
+     *
+     * @return the validation result
+     */
+    public ValidationResult validatePapRest() {
+        BeanValidationResult result = new BeanValidationResult(GROUPS_FIELD, this);
+
+        result.validateNotNullList(GROUPS_FIELD, groups, DeploymentGroup::validatePapRest);
+        if (!result.isValid()) {
+            return result;
+        }
+
+        // verify that the same group doesn't appear more than once
+        Set<String> sawGroup = new HashSet<>();
+        for (DeploymentGroup group : groups) {
+            String name = group.getName();
+            if (sawGroup.contains(name)) {
+                return new ObjectValidationResult(GROUPS_FIELD, name, ValidationStatus.INVALID, "duplicate group name");
+
+            } else {
+                sawGroup.add(name);
+            }
+        }
+
+        return result;
+    }
+}
diff --git a/models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/DeploymentSubGroup.java b/models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/DeploymentSubGroup.java
new file mode 100644
index 0000000..1a1fe22
--- /dev/null
+++ b/models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/DeploymentSubGroup.java
@@ -0,0 +1,82 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.pdp.concepts;
+
+import java.util.ArrayList;
+import java.util.List;
+import lombok.Data;
+import lombok.NonNull;
+import org.onap.policy.common.parameters.BeanValidationResult;
+import org.onap.policy.common.parameters.ValidationResult;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
+
+/**
+ * A deployment (i.e., set of policies) for all PDPs of the same pdp type running within a
+ * particular domain.
+ */
+@Data
+public class DeploymentSubGroup {
+
+    public enum Action {
+        POST,       // all listed policies are to be added
+        DELETE,     // all listed policies are to be deleted
+        PATCH       // update the deployment so that the policies match exactly
+    }
+
+    private String pdpType;
+    private Action action;
+    private List<ToscaPolicyIdentifier> policies;
+
+    /**
+     * Constructs the object.
+     */
+    public DeploymentSubGroup() {
+        super();
+    }
+
+    /**
+     * Constructs the object, making a deep copy from the source.
+     *
+     * @param source source from which to copy fields
+     */
+    public DeploymentSubGroup(@NonNull final DeploymentSubGroup source) {
+        this.pdpType = source.pdpType;
+        this.action = source.action;
+        this.policies = PfUtils.mapList(source.policies, ToscaPolicyIdentifier::new, new ArrayList<>(0));
+    }
+
+    /**
+     * Validates that appropriate fields are populated for an incoming call to the PAP
+     * REST API.
+     *
+     * @return the validation result
+     */
+    public ValidationResult validatePapRest() {
+        BeanValidationResult result = new BeanValidationResult("group", this);
+
+        result.validateNotNull("pdpType", pdpType);
+        result.validateNotNull("action", action);
+        result.validateNotNullList("policies", policies, ToscaPolicyIdentifier::validatePapRest);
+
+        return result;
+    }
+}
diff --git a/models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/PdpEngineWorkerStatistics.java b/models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/PdpEngineWorkerStatistics.java
new file mode 100644
index 0000000..43fa6c0
--- /dev/null
+++ b/models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/PdpEngineWorkerStatistics.java
@@ -0,0 +1,74 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.pdp.concepts;
+
+import java.io.Serializable;
+import javax.persistence.Embeddable;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import org.onap.policy.models.pdp.enums.PdpEngineWorkerState;
+
+@Embeddable
+@Getter
+@Setter
+@ToString
+@NoArgsConstructor
+public class PdpEngineWorkerStatistics implements Serializable {
+    private static final long serialVersionUID = 8262176849743624013L;
+
+    private String engineId;
+    private PdpEngineWorkerState engineWorkerState;
+    private long engineTimeStamp;
+    private long eventCount;
+    private long lastExecutionTime;
+    private double averageExecutionTime;
+    private long upTime;
+    private long lastEnterTime;
+    private long lastStart;
+
+    /**
+     * Constructs the object, making a deep copy.
+     *
+     * @param source source from which to copy
+     */
+    public PdpEngineWorkerStatistics(PdpEngineWorkerStatistics source) {
+        this.engineId = source.engineId;
+        this.engineWorkerState = source.engineWorkerState;
+        this.engineTimeStamp = source.engineTimeStamp;
+        this.eventCount = source.eventCount;
+        this.lastExecutionTime = source.lastExecutionTime;
+        this.averageExecutionTime = source.averageExecutionTime;
+        this.upTime = source.upTime;
+        this.lastEnterTime = source.lastEnterTime;
+        this.lastStart = source.lastStart;
+    }
+
+    /**
+     * Tidy up any superfluous information such as leading and trailing white space.
+     */
+    public void clean() {
+        if (engineId != null) {
+            engineId = engineId.trim();
+        }
+    }
+}
diff --git a/models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/PdpStatistics.java b/models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/PdpStatistics.java
index 1847eed..ad5547e 100644
--- a/models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/PdpStatistics.java
+++ b/models-pdp/src/main/java/org/onap/policy/models/pdp/concepts/PdpStatistics.java
@@ -21,10 +21,13 @@
 
 package org.onap.policy.models.pdp.concepts;
 
+import java.util.Date;
+import java.util.List;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 import lombok.Setter;
 import lombok.ToString;
+import org.onap.policy.models.base.PfUtils;
 
 /**
  * Class to represent statistics of a running PDP.
@@ -38,12 +41,16 @@
 public class PdpStatistics {
 
     private String pdpInstanceId;
+    private Date timeStamp;
+    private String pdpGroupName;
+    private String pdpSubGroupName;
     private long policyDeployCount;
     private long policyDeploySuccessCount;
     private long policyDeployFailCount;
     private long policyExecutedCount;
     private long policyExecutedSuccessCount;
     private long policyExecutedFailCount;
+    private List<PdpEngineWorkerStatistics> engineStats;
 
     /**
      * Constructs the object, making a deep copy.
@@ -52,11 +59,16 @@
      */
     public PdpStatistics(PdpStatistics source) {
         this.pdpInstanceId = source.pdpInstanceId;
+        this.timeStamp = source.timeStamp == null ? null : new Date(source.timeStamp.getTime());
+        this.pdpGroupName = source.pdpGroupName;
+        this.pdpSubGroupName = source.pdpSubGroupName;
         this.policyDeployCount = source.policyDeployCount;
         this.policyDeployFailCount = source.policyDeployFailCount;
         this.policyDeploySuccessCount = source.policyDeploySuccessCount;
         this.policyExecutedCount = source.policyExecutedCount;
         this.policyExecutedFailCount = source.policyExecutedFailCount;
         this.policyExecutedSuccessCount = source.policyExecutedSuccessCount;
+        this.engineStats = PfUtils.mapList(source.engineStats, PdpEngineWorkerStatistics::new, null);
     }
+
 }
diff --git a/models-pdp/src/main/java/org/onap/policy/models/pdp/enums/PdpEngineWorkerState.java b/models-pdp/src/main/java/org/onap/policy/models/pdp/enums/PdpEngineWorkerState.java
new file mode 100644
index 0000000..95b1947
--- /dev/null
+++ b/models-pdp/src/main/java/org/onap/policy/models/pdp/enums/PdpEngineWorkerState.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.pdp.enums;
+
+public enum PdpEngineWorkerState {
+    /** The state of the engine is not known. */
+    UNDEFINED,
+    /** The engine is stopped. */
+    STOPPED,
+    /** The engine is running and is waiting to execute a policy. */
+    READY,
+    /** The engine is running and is executing a policy. */
+    EXECUTING,
+    /** The engine has been ordered to stop and is stoping. */
+    STOPPING;
+}
diff --git a/models-pdp/src/main/java/org/onap/policy/models/pdp/persistence/concepts/JpaPdpStatistics.java b/models-pdp/src/main/java/org/onap/policy/models/pdp/persistence/concepts/JpaPdpStatistics.java
new file mode 100644
index 0000000..d08a19a
--- /dev/null
+++ b/models-pdp/src/main/java/org/onap/policy/models/pdp/persistence/concepts/JpaPdpStatistics.java
@@ -0,0 +1,230 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Model
+ * ================================================================================
+ * Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.pdp.persistence.concepts;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.Table;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NonNull;
+import org.apache.commons.lang3.builder.CompareToBuilder;
+import org.onap.policy.models.base.PfAuthorative;
+import org.onap.policy.models.base.PfConcept;
+import org.onap.policy.models.base.PfKey;
+import org.onap.policy.models.base.PfTimestampKey;
+import org.onap.policy.models.base.PfUtils;
+import org.onap.policy.models.base.PfValidationMessage;
+import org.onap.policy.models.base.PfValidationResult;
+import org.onap.policy.models.base.PfValidationResult.ValidationResult;
+import org.onap.policy.models.pdp.concepts.PdpEngineWorkerStatistics;
+import org.onap.policy.models.pdp.concepts.PdpStatistics;
+
+
+/**
+ * Class to represent a PDP statistics in the database.
+ *
+ */
+@Entity
+@Table(name = "PdpStatistics")
+@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
+@Data
+@AllArgsConstructor
+@EqualsAndHashCode(callSuper = false)
+public class JpaPdpStatistics extends PfConcept implements PfAuthorative<PdpStatistics>, Serializable {
+    private static final long serialVersionUID = -7312974966820980659L;
+    private static final String NULL_NAME = "NULL";
+
+    @EmbeddedId
+    private PfTimestampKey key;
+
+    @Column(length = 120)
+    private String pdpGroupName;
+
+    @Column(length = 120)
+    private String pdpSubGroupName;
+
+    @Column
+    private long policyDeployCount;
+
+    @Column
+    private long policyDeploySuccessCount;
+
+    @Column
+    private long policyDeployFailCount;
+
+    @Column
+    private long policyExecutedCount;
+
+    @Column
+    private long policyExecutedSuccessCount;
+
+    @Column
+    private long policyExecutedFailCount;
+
+    @ElementCollection
+    private List<PdpEngineWorkerStatistics> engineStats;
+
+    /**
+     * The Default Constructor creates a {@link JpaPdpStatistics} object with a null key.
+     */
+    public JpaPdpStatistics() {
+        this(new PfTimestampKey());
+    }
+
+    /**
+     * The Key Constructor creates a {@link JpaPdpStatistics} object with the given concept key.
+     *
+     * @param key the key
+     */
+    public JpaPdpStatistics(@NonNull final PfTimestampKey key) {
+        this(key, NULL_NAME, NULL_NAME, 0L, 0L, 0L, 0L, 0L, 0L, null);
+    }
+
+
+    /**
+     * Copy constructor.
+     *
+     * @param copyConcept the concept to copy from
+     */
+    public JpaPdpStatistics(@NonNull final JpaPdpStatistics copyConcept) {
+        super(copyConcept);
+        this.key = new PfTimestampKey(copyConcept.key);
+        this.pdpGroupName = copyConcept.pdpGroupName;
+        this.pdpSubGroupName = copyConcept.pdpSubGroupName;
+        this.policyDeployCount = copyConcept.policyDeployCount;
+        this.policyDeploySuccessCount = copyConcept.policyDeploySuccessCount;
+        this.policyDeployFailCount = copyConcept.policyDeployFailCount;
+        this.policyExecutedCount = copyConcept.policyExecutedCount;
+        this.policyExecutedSuccessCount = copyConcept.policyExecutedSuccessCount;
+        this.policyExecutedFailCount = copyConcept.policyExecutedFailCount;
+        this.engineStats = PfUtils.mapList(copyConcept.engineStats, PdpEngineWorkerStatistics::new, null);
+    }
+
+    /**
+     * Authorative constructor.
+     *
+     * @param authorativeConcept the authorative concept to copy from
+     */
+    public JpaPdpStatistics(@NonNull final PdpStatistics authorativeConcept) {
+        this.fromAuthorative(authorativeConcept);
+    }
+
+    @Override
+    public int compareTo(PfConcept otherConcept) {
+        if (otherConcept == null) {
+            return -1;
+        }
+        if (this == otherConcept) {
+            return 0;
+        }
+        if (getClass() != otherConcept.getClass()) {
+            return getClass().getName().compareTo(otherConcept.getClass().getName());
+        }
+
+        final JpaPdpStatistics other = (JpaPdpStatistics) otherConcept;
+        return new CompareToBuilder().append(this.key, other.key).append(this.pdpGroupName, other.pdpGroupName)
+                .append(this.pdpSubGroupName, other.pdpSubGroupName)
+                .append(this.policyDeployCount, other.policyDeployCount)
+                .append(this.policyDeployFailCount, other.policyDeployFailCount)
+                .append(this.policyDeploySuccessCount, other.policyDeploySuccessCount)
+                .append(this.policyExecutedCount, other.policyExecutedCount)
+                .append(this.policyExecutedFailCount, other.policyExecutedFailCount)
+                .append(this.policyExecutedSuccessCount, other.policyExecutedSuccessCount).toComparison();
+    }
+
+    @Override
+    public PdpStatistics toAuthorative() {
+        PdpStatistics pdpStatistics = new PdpStatistics();
+        pdpStatistics.setPdpInstanceId(key.getName());
+        pdpStatistics.setTimeStamp(new Date(key.getTimeStamp().getTime()));
+        pdpStatistics.setPdpGroupName(pdpGroupName);
+        pdpStatistics.setPdpSubGroupName(pdpSubGroupName);
+        pdpStatistics.setPolicyDeployCount(policyDeployCount);
+        pdpStatistics.setPolicyDeployFailCount(policyDeployFailCount);
+        pdpStatistics.setPolicyDeploySuccessCount(policyDeploySuccessCount);
+        pdpStatistics.setPolicyExecutedCount(policyExecutedCount);
+        pdpStatistics.setPolicyExecutedFailCount(policyExecutedFailCount);
+        pdpStatistics.setPolicyExecutedSuccessCount(policyExecutedSuccessCount);
+        pdpStatistics.setEngineStats(PfUtils.mapList(engineStats, PdpEngineWorkerStatistics::new, null));
+
+        return pdpStatistics;
+    }
+
+    @Override
+    public void fromAuthorative(@NonNull final PdpStatistics pdpStatistics) {
+        if (this.key == null || this.getKey().isNullKey()) {
+            this.setKey(new PfTimestampKey(pdpStatistics.getPdpInstanceId(), PfKey.NULL_KEY_VERSION,
+                    new Date(pdpStatistics.getTimeStamp() == null ? 0 : pdpStatistics.getTimeStamp().getTime())));
+        }
+        this.setPdpGroupName(pdpStatistics.getPdpGroupName());
+        this.setPdpSubGroupName(pdpStatistics.getPdpSubGroupName());
+        this.setPolicyDeployCount(pdpStatistics.getPolicyDeployCount());
+        this.setPolicyDeployFailCount(pdpStatistics.getPolicyDeployFailCount());
+        this.setPolicyDeploySuccessCount(pdpStatistics.getPolicyDeploySuccessCount());
+        this.setPolicyExecutedCount(pdpStatistics.getPolicyExecutedCount());
+        this.setPolicyExecutedFailCount(pdpStatistics.getPolicyExecutedFailCount());
+        this.setPolicyExecutedSuccessCount(pdpStatistics.getPolicyExecutedSuccessCount());
+        this.setEngineStats(
+                PfUtils.mapList(pdpStatistics.getEngineStats(), PdpEngineWorkerStatistics::new, null));
+    }
+
+    @Override
+    public List<PfKey> getKeys() {
+        return getKey().getKeys();
+    }
+
+    @Override
+    public PfValidationResult validate(@NonNull PfValidationResult resultIn) {
+        PfValidationResult result = resultIn;
+
+        if (key.isNullKey()) {
+            result.addValidationMessage(
+                    new PfValidationMessage(key, this.getClass(), ValidationResult.INVALID, "key is a null key"));
+        }
+
+        result = key.validate(result);
+
+        return result;
+    }
+
+    @Override
+    public void clean() {
+        key.clean();
+        pdpGroupName = pdpGroupName.trim();
+        pdpSubGroupName = pdpSubGroupName.trim();
+        if (engineStats != null) {
+            for (PdpEngineWorkerStatistics engineStat : engineStats) {
+                engineStat.clean();
+            }
+        }
+    }
+}
diff --git a/models-pdp/src/test/java/org/onap/policy/models/pdp/concepts/DeploymentGroupTest.java b/models-pdp/src/test/java/org/onap/policy/models/pdp/concepts/DeploymentGroupTest.java
new file mode 100644
index 0000000..a74029e
--- /dev/null
+++ b/models-pdp/src/test/java/org/onap/policy/models/pdp/concepts/DeploymentGroupTest.java
@@ -0,0 +1,194 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Models
+ * ================================================================================
+ * Copyright (C) 2019 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.models.pdp.concepts;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collections;
+import org.junit.Test;
+import org.onap.policy.common.parameters.ValidationResult;
+import org.onap.policy.models.pdp.concepts.DeploymentSubGroup.Action;
+
+/**
+ * Test methods not tested by {@link ModelsTest}.
+ */
+public class DeploymentGroupTest {
+    private static final String NAME = "my-name";
+    private static final String PDP_TYPE1 = "type-1";
+    private static final String PDP_TYPE2 = "type-2";
+    private static final String PDP_TYPE3 = "type-3";
+
+    @Test
+    public void testCopyConstructor() {
+        assertThatThrownBy(() -> new DeploymentGroup(null)).isInstanceOf(NullPointerException.class);
+
+        DeploymentGroup orig = new DeploymentGroup();
+
+        // verify with null values
+        assertEquals("DeploymentGroup(name=null, deploymentSubgroups=[])", new DeploymentGroup(orig).toString());
+
+        // verify with all values
+        orig.setName(NAME);
+
+        DeploymentSubGroup sub1 = new DeploymentSubGroup();
+        DeploymentSubGroup sub2 = new DeploymentSubGroup();
+        orig.setDeploymentSubgroups(Arrays.asList(sub1, sub2));
+
+        assertEquals("DeploymentGroup(name=my-name, "
+                        + "deploymentSubgroups=[DeploymentSubGroup(pdpType=null, action=null, policies=[]), "
+                        + "DeploymentSubGroup(pdpType=null, action=null, policies=[])])",
+                        new DeploymentGroup(orig).toString());
+    }
+
+    @Test
+    public void testHashCode() {
+        DeploymentGroup group = new DeploymentGroup();
+        group.setName("A");
+        int hash = group.hashCode();
+
+        assertEquals(hash, group.hashCode());
+
+        group.setName("B");
+        assertTrue(hash != group.hashCode());
+    }
+
+    @Test
+    public void testValidatePapRest() {
+        DeploymentGroup group = new DeploymentGroup();
+        group.setName(NAME);
+
+        DeploymentSubGroup subgroup1 = new DeploymentSubGroup();
+        subgroup1.setPdpType(PDP_TYPE1);
+        subgroup1.setAction(Action.PATCH);
+        subgroup1.setPolicies(Collections.emptyList());
+
+        DeploymentSubGroup subgroup2 = new DeploymentSubGroup(subgroup1);
+        subgroup2.setPdpType(PDP_TYPE2);
+
+        DeploymentSubGroup subgroup3 = new DeploymentSubGroup(subgroup1);
+        subgroup3.setPdpType(PDP_TYPE3);
+
+        group.setDeploymentSubgroups(Arrays.asList(subgroup1, subgroup2, subgroup3));
+
+        // valid
+        assertValid(group);
+
+        // null name
+        DeploymentGroup group2 = new DeploymentGroup(group);
+        group2.setName(null);
+        assertInvalid(group2);
+
+        // null subgroup list
+        group2 = new DeploymentGroup(group);
+        group2.setDeploymentSubgroups(null);
+        assertInvalid(group2);
+
+        // empty subgroup list
+        group2 = new DeploymentGroup(group);
+        group2.setDeploymentSubgroups(Collections.emptyList());
+        assertInvalid(group2);
+
+        // null subgroup
+        group2 = new DeploymentGroup(group);
+        group2.setDeploymentSubgroups(Arrays.asList(subgroup1, null));
+        assertInvalid(group2);
+
+        // invalid subgroup
+        group2 = new DeploymentGroup(group);
+        DeploymentSubGroup subgroupX = new DeploymentSubGroup(subgroup1);
+        subgroupX.setPdpType(null);
+        group2.setDeploymentSubgroups(Arrays.asList(subgroupX));
+        assertInvalid(group2);
+    }
+
+    @Test
+    public void testCheckDuplicateSubgroups() {
+        DeploymentGroup group = new DeploymentGroup();
+        group.setName(NAME);
+
+        DeploymentSubGroup subgroup1 = new DeploymentSubGroup();
+        subgroup1.setPdpType(PDP_TYPE1);
+        subgroup1.setAction(Action.POST);
+        subgroup1.setPolicies(Collections.emptyList());
+
+        DeploymentSubGroup subgroup2 = new DeploymentSubGroup(subgroup1);
+        subgroup2.setPdpType(PDP_TYPE2);
+        subgroup2.setAction(Action.PATCH);
+
+        DeploymentSubGroup subgroup3 = new DeploymentSubGroup(subgroup1);
+        subgroup3.setPdpType(PDP_TYPE3);
+        subgroup3.setAction(Action.DELETE);
+
+        group.setDeploymentSubgroups(Arrays.asList(subgroup1, subgroup2, subgroup3));
+
+        // no duplicates
+        assertValid(group);
+
+        /*
+         * Allowed duplicates
+         */
+        DeploymentSubGroup subgroup1b = new DeploymentSubGroup(subgroup1);
+        subgroup1b.setAction(Action.POST);
+
+        DeploymentSubGroup subgroup1c = new DeploymentSubGroup(subgroup1);
+        subgroup1c.setAction(Action.DELETE);
+
+        DeploymentSubGroup subgroup1d = new DeploymentSubGroup(subgroup1);
+        subgroup1d.setAction(Action.DELETE);
+
+        group.setDeploymentSubgroups(
+                        Arrays.asList(subgroup1, subgroup2, subgroup3, subgroup1b, subgroup1c, subgroup1d));
+
+        // still ok
+        assertValid(group);
+
+        /*
+         * Not allowed
+         */
+        DeploymentSubGroup subgroup1e = new DeploymentSubGroup(subgroup1);
+        subgroup1e.setAction(Action.PATCH);
+
+        group.setDeploymentSubgroups(
+                        Arrays.asList(subgroup1, subgroup2, subgroup3, subgroup1b, subgroup1c, subgroup1d, subgroup1e));
+
+        assertInvalid(group);
+    }
+
+    private void assertValid(DeploymentGroup group) {
+        ValidationResult result = group.validatePapRest();
+        assertNotNull(result);
+        assertNull(result.getResult());
+        assertTrue(result.isValid());
+    }
+
+    private void assertInvalid(DeploymentGroup group) {
+        ValidationResult result = group.validatePapRest();
+        assertNotNull(result);
+        assertFalse(result.isValid());
+        assertNotNull(result.getResult());
+    }
+}
diff --git a/models-pdp/src/test/java/org/onap/policy/models/pdp/concepts/DeploymentGroupsTest.java b/models-pdp/src/test/java/org/onap/policy/models/pdp/concepts/DeploymentGroupsTest.java
new file mode 100644
index 0000000..18b1375
--- /dev/null
+++ b/models-pdp/src/test/java/org/onap/policy/models/pdp/concepts/DeploymentGroupsTest.java
@@ -0,0 +1,89 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Models
+ * ================================================================================
+ * Copyright (C) 2019 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.models.pdp.concepts;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collections;
+import org.junit.Test;
+import org.onap.policy.common.parameters.ValidationResult;
+import org.onap.policy.models.pdp.concepts.DeploymentSubGroup.Action;
+
+public class DeploymentGroupsTest {
+
+    @Test
+    public void testValidatePapRest_toMapList() {
+        DeploymentGroup group1 = new DeploymentGroup();
+        group1.setName("group-1");
+
+        DeploymentSubGroup subgrp = new DeploymentSubGroup();
+        subgrp.setPdpType("pdp-type");
+        subgrp.setAction(Action.DELETE);
+        subgrp.setPolicies(Collections.emptyList());
+
+        group1.setDeploymentSubgroups(Arrays.asList(subgrp));
+
+        DeploymentGroup group2 = new DeploymentGroup();
+        group2.setName("group-2");
+        group2.setDeploymentSubgroups(Arrays.asList(subgrp));
+
+        DeploymentGroups groups = new DeploymentGroups();
+        groups.setGroups(Arrays.asList(group1, group2));
+
+        // valid
+        ValidationResult result = groups.validatePapRest();
+        assertNotNull(result);
+        assertNull(result.getResult());
+        assertTrue(result.isValid());
+
+        // null group list
+        groups = new DeploymentGroups();
+        groups.setGroups(null);
+        assertInvalid(groups);
+
+        // null group
+        groups = new DeploymentGroups();
+        groups.setGroups(Arrays.asList(group1, null));
+        assertInvalid(groups);
+
+        // invalid group
+        DeploymentGroup groupX = new DeploymentGroup(group1);
+        groupX.setName(null);
+        groups.setGroups(Arrays.asList(group1, groupX));
+        assertInvalid(groups);
+
+        // duplicate groups
+        groups = new DeploymentGroups();
+        groups.setGroups(Arrays.asList(group1, group2, group1));
+        assertInvalid(groups);
+    }
+
+    private void assertInvalid(DeploymentGroups groups) {
+        ValidationResult result = groups.validatePapRest();
+        assertNotNull(result);
+        assertFalse(result.isValid());
+        assertNotNull(result.getResult());
+    }
+}
diff --git a/models-pdp/src/test/java/org/onap/policy/models/pdp/concepts/DeploymentSubGroupTest.java b/models-pdp/src/test/java/org/onap/policy/models/pdp/concepts/DeploymentSubGroupTest.java
new file mode 100644
index 0000000..511d88f
--- /dev/null
+++ b/models-pdp/src/test/java/org/onap/policy/models/pdp/concepts/DeploymentSubGroupTest.java
@@ -0,0 +1,152 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP Policy Models
+ * ================================================================================
+ * Copyright (C) 2019 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.models.pdp.concepts;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import org.junit.Test;
+import org.onap.policy.common.parameters.ValidationResult;
+import org.onap.policy.common.utils.coder.Coder;
+import org.onap.policy.common.utils.coder.CoderException;
+import org.onap.policy.common.utils.coder.StandardCoder;
+import org.onap.policy.models.pdp.concepts.DeploymentSubGroup.Action;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
+
+/**
+ * Test methods not tested by {@link ModelsTest}.
+ */
+public class DeploymentSubGroupTest {
+    private static final String VERSION_300 = "3.0.0";
+    private static final Coder coder = new StandardCoder();
+
+    @Test
+    public void testCopyConstructor() {
+        assertThatThrownBy(() -> new DeploymentSubGroup(null)).isInstanceOf(NullPointerException.class);
+
+        final DeploymentSubGroup orig = new DeploymentSubGroup();
+
+        // verify with null values
+        assertEquals("DeploymentSubGroup(pdpType=null, action=null, policies=[])",
+                        new DeploymentSubGroup(orig).toString());
+
+        orig.setPdpType("my-type");
+        orig.setAction(Action.POST);
+
+        final ToscaPolicyIdentifier pol1 = new ToscaPolicyIdentifier();
+        pol1.setName("policy-A");
+        pol1.setVersion("1.0.0");
+        final ToscaPolicyIdentifier pol2 = new ToscaPolicyIdentifier();
+        pol2.setName("policy-B");
+        pol1.setVersion("2.0.0");
+        orig.setPolicies(Arrays.asList(pol1, pol2));
+
+        assertEquals(orig.toString(), new DeploymentSubGroup(orig).toString());
+    }
+
+    @Test
+    public void testValidatePapRest() throws Exception {
+        DeploymentSubGroup subgrp = new DeploymentSubGroup();
+
+        subgrp.setPdpType("pdp-type");
+        subgrp.setAction(Action.PATCH);
+        subgrp.setPolicies(Arrays.asList(makeIdent("policy-X", "4.0.0", ToscaPolicyIdentifier.class)));
+
+        // valid
+        ValidationResult result = subgrp.validatePapRest();
+        assertNotNull(result);
+        assertTrue(result.isValid());
+        assertNull(result.getResult());
+
+        // null pdp type
+        DeploymentSubGroup sub2 = new DeploymentSubGroup(subgrp);
+        sub2.setPdpType(null);
+        assertInvalid(sub2);
+
+        // null action
+        sub2 = new DeploymentSubGroup(subgrp);
+        sub2.setAction(null);
+        assertInvalid(sub2);
+
+        // null policies
+        sub2 = new DeploymentSubGroup(subgrp);
+        sub2.setPolicies(null);
+        assertInvalid(sub2);
+
+        // null policy item
+        sub2 = new DeploymentSubGroup(subgrp);
+        sub2.getPolicies().set(0, null);
+        assertInvalid(sub2);
+
+        // invalid policy item
+        sub2 = new DeploymentSubGroup(subgrp);
+        sub2.getPolicies().set(0, makeIdent(null, VERSION_300, ToscaPolicyIdentifier.class));
+        assertInvalid(sub2);
+    }
+
+    private void assertInvalid(DeploymentSubGroup sub2) {
+        ValidationResult result = sub2.validatePapRest();
+        assertNotNull(result);
+        assertFalse(result.isValid());
+        assertNotNull(result.getResult());
+    }
+
+    /**
+     * Makes an identifier. Uses JSON which does no error checking.
+     *
+     * @param name name to put into the identifier
+     * @param version version to put into the identifier
+     * @param clazz type of identifier to create
+     * @return a new identifier
+     * @throws CoderException if the JSON cannot be decoded
+     */
+    private <T> T makeIdent(String name, String version, Class<T> clazz) throws CoderException {
+        StringBuilder bldr = new StringBuilder();
+        bldr.append("{");
+
+        if (name != null) {
+            bldr.append("'name':'");
+            bldr.append(name);
+            bldr.append("'");
+        }
+
+        if (version != null) {
+            if (name != null) {
+                bldr.append(',');
+            }
+
+            bldr.append("'version':'");
+            bldr.append(version);
+            bldr.append("'");
+        }
+
+        bldr.append("}");
+
+        String json = bldr.toString().replace('\'', '"');
+
+        return coder.decode(json, clazz);
+    }
+}
diff --git a/models-pdp/src/test/java/org/onap/policy/models/pdp/persistence/concepts/JpaPdpStatisticsTest.java b/models-pdp/src/test/java/org/onap/policy/models/pdp/persistence/concepts/JpaPdpStatisticsTest.java
new file mode 100644
index 0000000..62f0c5b
--- /dev/null
+++ b/models-pdp/src/test/java/org/onap/policy/models/pdp/persistence/concepts/JpaPdpStatisticsTest.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.pdp.persistence.concepts;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.junit.Test;
+
+/**
+ * Test the {@link JpaPdpStatistics} class.
+ *
+ */
+public class JpaPdpStatisticsTest {
+    private static final String NULL_KEY_ERROR = "key is marked @NonNull but is null";
+    private static final String PDP1 = "ThePDP";
+
+    // TODO More unit test cases will be added later.
+    @Test
+    public void testJpaPdpStatistics() {
+        assertThatThrownBy(() -> {
+            new JpaPdpStatistics((JpaPdpStatistics) null);
+        }).hasMessage("copyConcept is marked @NonNull but is null");
+    }
+}
diff --git a/models-pdp/src/test/java/org/onap/policy/models/pdp/testconcepts/DummyJpaPdpStatisticsChild.java b/models-pdp/src/test/java/org/onap/policy/models/pdp/testconcepts/DummyJpaPdpStatisticsChild.java
new file mode 100644
index 0000000..b428fc6
--- /dev/null
+++ b/models-pdp/src/test/java/org/onap/policy/models/pdp/testconcepts/DummyJpaPdpStatisticsChild.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2019 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.pdp.testconcepts;
+
+import org.onap.policy.models.pdp.persistence.concepts.JpaPdpStatistics;
+
+/**
+ * Test class for JpaPdpStatistics comparisons.
+ *
+ */
+
+public class DummyJpaPdpStatisticsChild extends JpaPdpStatistics {
+
+    private static final long serialVersionUID = -5911806849612508805L;
+
+}
diff --git a/models-pdp/src/test/resources/META-INF/persistence.xml b/models-pdp/src/test/resources/META-INF/persistence.xml
index 9d78e3a..b1a1795 100644
--- a/models-pdp/src/test/resources/META-INF/persistence.xml
+++ b/models-pdp/src/test/resources/META-INF/persistence.xml
@@ -31,6 +31,7 @@
         <class>org.onap.policy.models.pdp.persistence.concepts.JpaPdpGroup</class>
         <class>org.onap.policy.models.pdp.persistence.concepts.JpaPdpSubGroup</class>
         <class>org.onap.policy.models.pdp.persistence.concepts.JpaPdp</class>
+        <class>org.onap.policy.models.pdp.persistence.concepts.JpaPdpStatistics</class>
 
         <properties>
             <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
diff --git a/models-provider/src/test/java/org/onap/policy/models/provider/impl/PolicyTypePersistenceTest.java b/models-provider/src/test/java/org/onap/policy/models/provider/impl/PolicyTypePersistenceTest.java
index 2ccf215..75f21d2 100644
--- a/models-provider/src/test/java/org/onap/policy/models/provider/impl/PolicyTypePersistenceTest.java
+++ b/models-provider/src/test/java/org/onap/policy/models/provider/impl/PolicyTypePersistenceTest.java
@@ -64,17 +64,17 @@
     // @formatter:off
     private String[] policyTypeResourceNames = {
         "policytypes/onap.policies.controlloop.Operational.yaml",
-        "policytypes/onap.policies.optimization.DistancePolicy.yaml",
-        "policytypes/onap.policies.optimization.VnfPolicy.yaml",
-        "policytypes/onap.policies.optimization.PciPolicy.yaml",
-        "policytypes/onap.policies.optimization.OptimizationPolicy.yaml",
+        "policytypes/onap.policies.optimization.resource.DistancePolicy.yaml",
+        "policytypes/onap.policies.optimization.resource.VnfPolicy.yaml",
+        "policytypes/onap.policies.optimization.resource.PciPolicy.yaml",
+        "policytypes/onap.policies.optimization.resource.OptimizationPolicy.yaml",
         "policytypes/onap.policies.controlloop.guard.Blacklist.yaml",
         "policytypes/onap.policies.monitoring.dcaegen2.collectors.datafile.datafile-app-server.yaml",
-        "policytypes/onap.policies.optimization.HpaPolicy.yaml",
-        "policytypes/onap.policies.optimization.Vim_fit.yaml",
-        "policytypes/onap.policies.optimization.SubscriberPolicy.yaml",
-        "policytypes/onap.policies.optimization.AffinityPolicy.yaml",
-        "policytypes/onap.policies.optimization.QueryPolicy.yaml",
+        "policytypes/onap.policies.optimization.resource.HpaPolicy.yaml",
+        "policytypes/onap.policies.optimization.resource.Vim_fit.yaml",
+        "policytypes/onap.policies.optimization.service.SubscriberPolicy.yaml",
+        "policytypes/onap.policies.optimization.resource.AffinityPolicy.yaml",
+        "policytypes/onap.policies.optimization.service.QueryPolicy.yaml",
         "policytypes/onap.policies.controlloop.guard.MinMax.yaml",
         "policytypes/onap.policies.controlloop.guard.FrequencyLimiter.yaml",
         "policytypes/onap.policies.controlloop.guard.coordination.FirstBlocksSecond.yaml",
diff --git a/models-provider/src/test/resources/META-INF/persistence.xml b/models-provider/src/test/resources/META-INF/persistence.xml
index 7b5bc14..48f1b10 100644
--- a/models-provider/src/test/resources/META-INF/persistence.xml
+++ b/models-provider/src/test/resources/META-INF/persistence.xml
@@ -31,6 +31,7 @@
         <class>org.onap.policy.models.pdp.persistence.concepts.JpaPdpGroup</class>
         <class>org.onap.policy.models.pdp.persistence.concepts.JpaPdpSubGroup</class>
         <class>org.onap.policy.models.pdp.persistence.concepts.JpaPdp</class>
+        <class>org.onap.policy.models.pdp.persistence.concepts.JpaPdpStatistics</class>
 
         <properties>
             <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
diff --git a/models-tosca/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyFilterTest.java b/models-tosca/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyFilterTest.java
index 2c62e7f..34feece 100644
--- a/models-tosca/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyFilterTest.java
+++ b/models-tosca/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyFilterTest.java
@@ -144,26 +144,26 @@
         ToscaPolicyFilter filter = ToscaPolicyFilter.builder().version(ToscaPolicyFilter.LATEST_VERSION).build();
 
         List<ToscaPolicy> filteredList = filter.filter(policyList);
-        assertEquals(15, filteredList.size());
+        assertEquals(22, filteredList.size());
         assertEquals(VERSION_100, filteredList.get(7).getVersion());
         assertEquals(VERSION_100, filteredList.get(12).getVersion());
 
-        assertEquals(17, policyList.size());
-        assertEquals(15, filteredList.size());
+        assertEquals(24, policyList.size());
+        assertEquals(22, filteredList.size());
 
         policyList.get(10).setVersion("2.0.0");
         policyList.get(16).setVersion("3.4.5");
         filteredList = filter.filter(policyList);
-        assertEquals(15, filteredList.size());
-        assertEquals("2.0.0", filteredList.get(7).getVersion());
-        assertEquals("3.4.5", filteredList.get(12).getVersion());
+        assertEquals(22, filteredList.size());
+        assertEquals("2.0.0", filteredList.get(12).getVersion());
+        assertEquals("3.4.5", filteredList.get(14).getVersion());
 
         policyList.get(10).setVersion(VERSION_100);
         policyList.get(16).setVersion(VERSION_100);
         filteredList = filter.filter(policyList);
-        assertEquals(15, filteredList.size());
-        assertEquals(VERSION_100, filteredList.get(7).getVersion());
+        assertEquals(22, filteredList.size());
         assertEquals(VERSION_100, filteredList.get(12).getVersion());
+        assertEquals(VERSION_100, filteredList.get(14).getVersion());
     }
 
     @Test
@@ -182,7 +182,7 @@
 
         filter = ToscaPolicyFilter.builder().version(VERSION_100).build();
         filteredList = filter.filter(policyList);
-        assertEquals(15, filteredList.size());
+        assertEquals(21, filteredList.size());
 
         filter = ToscaPolicyFilter.builder().name("OSDF_CASABLANCA.SubscriberPolicy_v1").version(VERSION_100).build();
         filteredList = filter.filter(policyList);
@@ -190,7 +190,7 @@
 
         filter = ToscaPolicyFilter.builder().name("operational.modifyconfig").version(VERSION_100).build();
         filteredList = filter.filter(policyList);
-        assertEquals(2, filteredList.size());
+        assertEquals(1, filteredList.size());
     }
 
     @Test
@@ -198,11 +198,11 @@
         // null pattern
         ToscaPolicyFilter filter = ToscaPolicyFilter.builder().versionPrefix(null).build();
         List<ToscaPolicy> filteredList = filter.filter(policyList);
-        assertEquals(17, filteredList.size());
+        assertEquals(24, filteredList.size());
 
         filter = ToscaPolicyFilter.builder().versionPrefix("1.").build();
         filteredList = filter.filter(policyList);
-        assertEquals(14, filteredList.size());
+        assertEquals(21, filteredList.size());
 
         filter = ToscaPolicyFilter.builder().versionPrefix("100.").build();
         filteredList = filter.filter(policyList);
@@ -229,12 +229,12 @@
 
         filter = ToscaPolicyFilter.builder().typeVersion(VERSION_000).build();
         filteredList = filter.filter(policyList);
-        assertEquals(14, filteredList.size());
+        assertEquals(7, filteredList.size());
 
-        filter = ToscaPolicyFilter.builder().type("onap.policies.optimization.HpaPolicy").typeVersion(VERSION_000)
-                        .build();
+        filter = ToscaPolicyFilter.builder().type("onap.policies.optimization.resource.HpaPolicy")
+                .typeVersion(VERSION_100).build();
         filteredList = filter.filter(policyList);
-        assertEquals(1, filteredList.size());
+        assertEquals(2, filteredList.size());
 
         filter = ToscaPolicyFilter.builder().type("onap.policies.controlloop.Operational").typeVersion(VERSION_000)
                         .build();
diff --git a/models-tosca/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyTypeFilterTest.java b/models-tosca/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyTypeFilterTest.java
index d9ffec5..f4f822c 100644
--- a/models-tosca/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyTypeFilterTest.java
+++ b/models-tosca/src/test/java/org/onap/policy/models/tosca/authorative/concepts/ToscaPolicyTypeFilterTest.java
@@ -27,12 +27,10 @@
 import static org.junit.Assert.assertTrue;
 
 import com.google.gson.GsonBuilder;
-
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-
 import org.junit.BeforeClass;
 import org.junit.Test;
 import org.onap.policy.common.utils.coder.CoderException;
@@ -59,17 +57,17 @@
     // @formatter:off
     private static final String[] policyTypeResourceNames = {
         "policytypes/onap.policies.controlloop.Operational.yaml",
-        "policytypes/onap.policies.optimization.DistancePolicy.yaml",
-        "policytypes/onap.policies.optimization.VnfPolicy.yaml",
-        "policytypes/onap.policies.optimization.PciPolicy.yaml",
-        "policytypes/onap.policies.optimization.OptimizationPolicy.yaml",
+        "policytypes/onap.policies.optimization.resource.DistancePolicy.yaml",
+        "policytypes/onap.policies.optimization.resource.VnfPolicy.yaml",
+        "policytypes/onap.policies.optimization.resource.PciPolicy.yaml",
+        "policytypes/onap.policies.optimization.resource.OptimizationPolicy.yaml",
         "policytypes/onap.policies.controlloop.guard.Blacklist.yaml",
         "policytypes/onap.policies.monitoring.dcaegen2.collectors.datafile.datafile-app-server.yaml",
-        "policytypes/onap.policies.optimization.HpaPolicy.yaml",
-        "policytypes/onap.policies.optimization.Vim_fit.yaml",
-        "policytypes/onap.policies.optimization.SubscriberPolicy.yaml",
-        "policytypes/onap.policies.optimization.AffinityPolicy.yaml",
-        "policytypes/onap.policies.optimization.QueryPolicy.yaml",
+        "policytypes/onap.policies.optimization.resource.HpaPolicy.yaml",
+        "policytypes/onap.policies.optimization.resource.Vim_fit.yaml",
+        "policytypes/onap.policies.optimization.service.SubscriberPolicy.yaml",
+        "policytypes/onap.policies.optimization.resource.AffinityPolicy.yaml",
+        "policytypes/onap.policies.optimization.service.QueryPolicy.yaml",
         "policytypes/onap.policies.controlloop.guard.MinMax.yaml",
         "policytypes/onap.policies.controlloop.guard.FrequencyLimiter.yaml",
         "policytypes/onap.policies.controlloop.guard.coordination.FirstBlocksSecond.yaml",
diff --git a/models-tosca/src/test/java/org/onap/policy/models/tosca/simple/serialization/OptimizationPolicyTypeSerializationTest.java b/models-tosca/src/test/java/org/onap/policy/models/tosca/simple/serialization/OptimizationPolicyTypeSerializationTest.java
index 9f99069..e710faa 100644
--- a/models-tosca/src/test/java/org/onap/policy/models/tosca/simple/serialization/OptimizationPolicyTypeSerializationTest.java
+++ b/models-tosca/src/test/java/org/onap/policy/models/tosca/simple/serialization/OptimizationPolicyTypeSerializationTest.java
@@ -44,7 +44,10 @@
     private static final String TYPE_ROOT = "tosca.policies.Root";
     private static final String VERSION = "1.0.0";
 
-    private static final String INPUT_YAML = "policytypes/onap.policies.Optimization.yaml";
+    private static final String INPUT_OPTIMIZATION_YAML = "policytypes/onap.policies.Optimization.yaml";
+    private static final String INPUT_OPTIMIZATION_RESOURCE_YAML =
+            "policytypes/onap.policies.optimization.Resource.yaml";
+    private static final String INPUT_OPTIMIZATION_SERVICE_YAML = "policytypes/onap.policies.optimization.Service.yaml";
 
     private StandardCoder coder;
 
@@ -54,13 +57,39 @@
     }
 
     @Test
-    public void test() throws CoderException {
-        JpaToscaServiceTemplate svctmpl = loadYaml(INPUT_YAML);
-        validate("initial object", svctmpl);
+    public void testOptimization() throws CoderException {
+        JpaToscaServiceTemplate svctmpl = loadYaml(INPUT_OPTIMIZATION_YAML);
+        validate("initial object", svctmpl, TYPE_ROOT, "onap.policies.Optimization", false, false);
 
         String ser = serialize(svctmpl);
         JpaToscaServiceTemplate svctmpl2 = deserialize(ser);
-        validate("copy", svctmpl2);
+        validate("copy", svctmpl2, TYPE_ROOT, "onap.policies.Optimization", false, false);
+
+        assertEquals(svctmpl, svctmpl2);
+    }
+
+    @Test
+    public void testOptimizationResource() throws CoderException {
+        JpaToscaServiceTemplate svctmpl = loadYaml(INPUT_OPTIMIZATION_RESOURCE_YAML);
+        validate("initial object", svctmpl, "onap.policies.Optimization", "onap.policies.optimization.Resource", true,
+                true);
+
+        String ser = serialize(svctmpl);
+        JpaToscaServiceTemplate svctmpl2 = deserialize(ser);
+        validate("copy", svctmpl2, "onap.policies.Optimization", "onap.policies.optimization.Resource", true, true);
+
+        assertEquals(svctmpl, svctmpl2);
+    }
+
+    @Test
+    public void testOptimizationService() throws CoderException {
+        JpaToscaServiceTemplate svctmpl = loadYaml(INPUT_OPTIMIZATION_SERVICE_YAML);
+        validate("initial object", svctmpl, "onap.policies.Optimization", "onap.policies.optimization.Service", false,
+                true);
+
+        String ser = serialize(svctmpl);
+        JpaToscaServiceTemplate svctmpl2 = deserialize(ser);
+        validate("copy", svctmpl2, "onap.policies.Optimization", "onap.policies.optimization.Service", false, true);
 
         assertEquals(svctmpl, svctmpl2);
     }
@@ -86,29 +115,32 @@
         return coder.encode(auth);
     }
 
-    private void validate(String testnm, JpaToscaServiceTemplate svctmpl) {
+    private void validate(String testnm, JpaToscaServiceTemplate svctmpl, String derivedFrom,
+            String typeName, boolean checkResource, boolean checkService) {
         JpaToscaPolicyTypes policyTypes = svctmpl.getPolicyTypes();
 
         assertEquals(testnm + " type count", 1, policyTypes.getConceptMap().size());
         JpaToscaPolicyType policyType = policyTypes.getConceptMap().values().iterator().next();
 
-        assertEquals(testnm + " name", "onap.policies.Optimization", policyType.getName());
+        assertEquals(testnm + " name", typeName, policyType.getName());
         assertEquals(testnm + " version", VERSION, policyType.getVersion());
 
         assertNotNull(testnm + " derived from", policyType.getDerivedFrom());
-        assertEquals(testnm + " derived from name", TYPE_ROOT, policyType.getDerivedFrom().getName());
-
-        assertEquals(testnm + " description", "The base policy type for all policies that govern optimization",
-                        policyType.getDescription());
+        assertEquals(testnm + " derived from name", derivedFrom, policyType.getDerivedFrom().getName());
 
         Map<String, JpaToscaProperty> props = policyType.getProperties();
         assertNotNull(testnm + " properties", props);
 
-        validateScope(testnm, props.get("scope"));
-        validateServices(testnm, props.get("services"));
-        validateResources(testnm, props.get("resources"));
-        validateGeography(testnm, props.get("geography"));
-        validateIdentity(testnm, props.get("identity"));
+        if (checkResource && checkService) {
+            validateResources(testnm, props.get("resources"));
+            validateServices(testnm, props.get("services"));
+        } else if (checkService && !checkResource) {
+            validateServices(testnm, props.get("services"));
+        } else {
+            validateScope(testnm, props.get("scope"));
+            validateGeography(testnm, props.get("geography"));
+            validateIdentity(testnm, props.get("identity"));
+        }
     }
 
     // only need to validate deep match of one of these; geography is the most interesting