Add DAO module for Models

This patch set fixes some typos and license headers.

Issue-ID: POLICY-1195
Change-Id: I2d15b00fcb50ea92746ab7c5a87b57efa07196fe
Signed-off-by: liamfallon <liam.fallon@est.tech>
diff --git a/models-dao/src/main/java/org/onap/policy/models/dao/DaoParameters.java b/models-dao/src/main/java/org/onap/policy/models/dao/DaoParameters.java
new file mode 100644
index 0000000..18ae74a
--- /dev/null
+++ b/models-dao/src/main/java/org/onap/policy/models/dao/DaoParameters.java
@@ -0,0 +1,126 @@
+/*-
+ * ============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.dao;
+
+import java.util.Properties;
+
+/**
+ * This class is a POJO that holds properties for PF DAOs.
+ */
+public class DaoParameters {
+    /** The default PF DAO plugin class. */
+    public static final String DEFAULT_PLUGIN_CLASS = "org.onap.policy.models.dao.impl.DefaultPfDao";
+
+    private String pluginClass = DEFAULT_PLUGIN_CLASS;
+    private String persistenceUnit;
+
+    private Properties jdbcProperties = new Properties();
+
+    /**
+     * Gets the DAO plugin class, this is the DAO class to use and it must implement the
+     * {@link PfDao} interface.
+     *
+     * @return the DAO plugin class
+     */
+    public String getPluginClass() {
+        return pluginClass;
+    }
+
+    /**
+     * Sets the DAO plugin class, a class that implements the {@link PfDao} interface.
+     *
+     * @param daoPluginClass the DAO plugin class
+     */
+    public void setPluginClass(final String daoPluginClass) {
+        pluginClass = daoPluginClass;
+    }
+
+    /**
+     * Gets the persistence unit for the DAO. The persistence unit defines the JDBC properties the
+     * DAO will use. The persistence unit must defined in the {@code META-INF/persistence.xml}
+     * resource file
+     *
+     * @return the persistence unit to use for JDBC access
+     */
+    public String getPersistenceUnit() {
+        return persistenceUnit;
+    }
+
+    /**
+     * Sets the persistence unit for the DAO. The persistence unit defines the JDBC properties the
+     * DAO will use. The persistence unit must defined in the {@code META-INF/persistence.xml}
+     * resource file
+     *
+     * @param daoPersistenceUnit the persistence unit to use for JDBC access
+     */
+    public void setPersistenceUnit(final String daoPersistenceUnit) {
+        persistenceUnit = daoPersistenceUnit;
+    }
+
+    /**
+     * Gets the JDBC properties.
+     *
+     * @return the JDBC properties
+     */
+    public Properties getJdbcProperties() {
+        return jdbcProperties;
+    }
+
+    /**
+     * Sets the JDBC properties.
+     *
+     * @param jdbcProperties the JDBC properties
+     */
+    public void setJdbcProperties(final Properties jdbcProperties) {
+        this.jdbcProperties = jdbcProperties;
+    }
+
+    /**
+     * Gets a single JDBC property.
+     *
+     * @param key the key of the property
+     * @return the JDBC property
+     */
+    public String getJdbcProperty(final String key) {
+        return jdbcProperties.getProperty(key);
+    }
+
+    /**
+     * Sets a single JDBC property.
+     *
+     * @param key the key of the property
+     * @param value the value of the JDBC property
+     */
+    public void setJdbcProperty(final String key, final String value) {
+        jdbcProperties.setProperty(key, value);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return "DAOParameters [pluginClass=" + pluginClass + ", persistenceUnit=" + persistenceUnit
+                + ", jdbcProperties=" + jdbcProperties + "]";
+    }
+}
diff --git a/models-dao/src/main/java/org/onap/policy/models/dao/PfDao.java b/models-dao/src/main/java/org/onap/policy/models/dao/PfDao.java
new file mode 100644
index 0000000..85c971c
--- /dev/null
+++ b/models-dao/src/main/java/org/onap/policy/models/dao/PfDao.java
@@ -0,0 +1,205 @@
+/*-
+ * ============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.dao;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.onap.policy.models.base.PfConcept;
+import org.onap.policy.models.base.PfConceptKey;
+import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.base.PfReferenceKey;
+
+/**
+ * The Interface PfDao describes the DAO interface for reading and writing Policy Framework
+ * {@link PfConcept} concepts to and from databases using JDBC.
+ */
+public interface PfDao {
+
+    /**
+     * Initialize the Policy Framework DAO with the given parameters.
+     *
+     * @param daoParameters parameters to use to access the database
+     * @throws PfModelException on initialization errors
+     */
+    void init(DaoParameters daoParameters) throws PfModelException;
+
+    /**
+     * Close the Policy Framework DAO.
+     */
+    void close();
+
+    /**
+     * Creates an Policy Framework concept on the database.
+     *
+     * @param <T> the type of the object to create, a subclass of {@link PfConcept}
+     * @param obj the object to create
+     */
+    <T extends PfConcept> void create(T obj);
+
+    /**
+     * Delete an Policy Framework concept on the database.
+     *
+     * @param <T> the type of the object to delete, a subclass of {@link PfConcept}
+     * @param obj the object to delete
+     */
+    <T extends PfConcept> void delete(T obj);
+
+    /**
+     * Delete an Policy Framework concept on the database.
+     *
+     * @param <T> the type of the object to delete, a subclass of {@link PfConcept}
+     * @param someClass the class of the object to delete, a subclass of {@link PfConcept}
+     * @param key the key of the object to delete
+     */
+    <T extends PfConcept> void delete(Class<T> someClass, PfConceptKey key);
+
+    /**
+     * Delete an Policy Framework concept on the database.
+     *
+     * @param <T> the type of the object to delete, a subclass of {@link PfConcept}
+     * @param someClass the class of the object to delete, a subclass of {@link PfConcept}
+     * @param key the key of the object to delete
+     */
+    <T extends PfConcept> void delete(Class<T> someClass, PfReferenceKey key);
+
+    /**
+     * Create a collection of objects in the database.
+     *
+     * @param <T> the type of the object to create, a subclass of {@link PfConcept}
+     * @param objs the objects to create
+     */
+    <T extends PfConcept> void createCollection(Collection<T> objs);
+
+    /**
+     * Delete a collection of objects in the database.
+     *
+     * @param <T> the type of the objects to delete, a subclass of {@link PfConcept}
+     * @param objs the objects to delete
+     */
+    <T extends PfConcept> void deleteCollection(Collection<T> objs);
+
+    /**
+     * Delete a collection of objects in the database referred to by concept key.
+     *
+     * @param <T> the type of the objects to delete, a subclass of {@link PfConcept}
+     * @param someClass the class of the objects to delete, a subclass of {@link PfConcept}
+     * @param keys the keys of the objects to delete
+     * @return the number of objects deleted
+     */
+    <T extends PfConcept> int deleteByConceptKey(Class<T> someClass, Collection<PfConceptKey> keys);
+
+    /**
+     * Delete a collection of objects in the database referred to by reference key.
+     *
+     * @param <T> the type of the objects to delete, a subclass of {@link PfConcept}
+     * @param someClass the class of the objects to delete, a subclass of {@link PfConcept}
+     * @param keys the keys of the objects to delete
+     * @return the number of objects deleted
+     */
+    <T extends PfConcept> int deleteByReferenceKey(Class<T> someClass, Collection<PfReferenceKey> keys);
+
+    /**
+     * Delete all objects of a given class in the database.
+     *
+     * @param <T> the type of the objects to delete, a subclass of {@link PfConcept}
+     * @param someClass the class of the objects to delete, a subclass of {@link PfConcept}
+     */
+    <T extends PfConcept> void deleteAll(Class<T> someClass);
+
+    /**
+     * Get an object from the database, referred to by concept key.
+     *
+     * @param <T> the type of the object to get, a subclass of {@link PfConcept}
+     * @param someClass the class of the object to get, a subclass of {@link PfConcept}
+     * @param key the key of the object to get
+     * @return the object that was retrieved from the database
+     */
+    <T extends PfConcept> T get(Class<T> someClass, PfConceptKey key);
+
+    /**
+     * Get an object from the database, referred to by reference key.
+     *
+     * @param <T> the type of the object to get, a subclass of {@link PfConcept}
+     * @param someClass the class of the object to get, a subclass of {@link PfConcept}
+     * @param key the key of the object to get
+     * @return the object that was retrieved from the database or null if the object was not
+     *         retrieved
+     */
+    <T extends PfConcept> T get(Class<T> someClass, PfReferenceKey key);
+
+    /**
+     * Get all the objects in the database of a given type.
+     *
+     * @param <T> the type of the objects to get, a subclass of {@link PfConcept}
+     * @param someClass the class of the objects to get, a subclass of {@link PfConcept}
+     * @return the objects or null if no objects were retrieved
+     */
+    <T extends PfConcept> List<T> getAll(Class<T> someClass);
+
+    /**
+     * Get all the objects in the database of the given type with the given parent concept key.
+     *
+     * @param <T> the type of the objects to get, a subclass of {@link PfConcept}
+     * @param someClass the class of the objects to get, a subclass of {@link PfConcept}
+     * @param parentKey the parent key of the concepts to get
+     * @return the all
+     */
+    <T extends PfConcept> List<T> getAll(Class<T> someClass, PfConceptKey parentKey);
+
+    /**
+     * Get a concept from the database with the given concept key.
+     *
+     * @param <T> the type of the object to get, a subclass of {@link PfConcept}
+     * @param someClass the class of the object to get, a subclass of {@link PfConcept}
+     * @param conceptId the concept key of the concept to get
+     * @return the concept that matches the key or null if the concept is not retrieved
+     */
+    <T extends PfConcept> T getConcept(Class<T> someClass, PfConceptKey conceptId);
+
+    /**
+     * Get a concept from the database with the given reference key.
+     *
+     * @param <T> the type of the object to get, a subclass of {@link PfConcept}
+     * @param someClass the class of the object to get, a subclass of {@link PfConcept}
+     * @param conceptId the concept key of the concept to get
+     * @return the concept that matches the key or null if the concept is not retrieved
+     */
+    <T extends PfConcept> T getConcept(Class<T> someClass, PfReferenceKey conceptId);
+
+    /**
+     * Get the number of instances of a concept that exist in the database.
+     *
+     * @param <T> the type of the object to get, a subclass of {@link PfConcept}
+     * @param someClass the class of the object to get, a subclass of {@link PfConcept}
+     * @return the number of instances of the concept in the database
+     */
+    <T extends PfConcept> long size(Class<T> someClass);
+
+    /**
+     * Update a concept in the database.
+     *
+     * @param <T> the type of the object to get, a subclass of {@link PfConcept}
+     * @param obj the object to update
+     * @return the updated object
+     */
+    <T extends PfConcept> T update(T obj);
+}
diff --git a/models-dao/src/main/java/org/onap/policy/models/dao/PfDaoFactory.java b/models-dao/src/main/java/org/onap/policy/models/dao/PfDaoFactory.java
new file mode 100644
index 0000000..3b7e31e
--- /dev/null
+++ b/models-dao/src/main/java/org/onap/policy/models/dao/PfDaoFactory.java
@@ -0,0 +1,68 @@
+/*-
+ * ============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.dao;
+
+import org.onap.policy.common.utils.validation.Assertions;
+import org.onap.policy.models.base.PfModelException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This factory class returns a Policy Framework DAO for the configured persistence mechanism. The
+ * factory uses the plugin class specified in {@link DaoParameters} to instantiate a DAO instance.
+ */
+public class PfDaoFactory {
+    // Get a reference to the logger
+    private static final Logger LOGGER = LoggerFactory.getLogger(PfDaoFactory.class);
+
+    /**
+     * Return a Policy Framework DAO for the required Policy Framework DAO plugin class.
+     *
+     * @param daoParameters parameters to use to read the database configuration information
+     * @return the Policy Framework DAO
+     * @throws PfModelException on invalid JPA plugins
+     */
+    public PfDao createPfDao(final DaoParameters daoParameters) throws PfModelException {
+        Assertions.argumentOfClassNotNull(daoParameters, PfModelException.class,
+                "Parameter \"daoParameters\" may not be null");
+
+        // Get the class for the DAO using reflection
+        Object pfDaoObject = null;
+        try {
+            pfDaoObject = Class.forName(daoParameters.getPluginClass()).newInstance();
+        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
+            String errorMessage =
+                    "Policy Framework DAO class not found for DAO plugin \"" + daoParameters.getPluginClass() + "\"";
+            LOGGER.error(errorMessage, e);
+            throw new PfModelException(errorMessage, e);
+        }
+
+        // Check the class is a Policy Framework DAO
+        if (!(pfDaoObject instanceof PfDao)) {
+            String errorMessage = "Specified DAO plugin class \"" + daoParameters.getPluginClass()
+                    + "\" does not implement the PfDao interface";
+            LOGGER.error(errorMessage);
+            throw new PfModelException(errorMessage);
+        }
+
+        return (PfDao) pfDaoObject;
+    }
+}
diff --git a/models-dao/src/main/java/org/onap/policy/models/dao/converters/CDataConditioner.java b/models-dao/src/main/java/org/onap/policy/models/dao/converters/CDataConditioner.java
new file mode 100644
index 0000000..327f65e
--- /dev/null
+++ b/models-dao/src/main/java/org/onap/policy/models/dao/converters/CDataConditioner.java
@@ -0,0 +1,69 @@
+/*-
+ * ============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.dao.converters;
+
+import javax.persistence.AttributeConverter;
+import javax.persistence.Converter;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+/**
+ * The Class CDATAConditioner converts a CDATA String to and from database format by removing spaces
+ * at the ends of lines and platform-specific new line endings.
+ */
+@Converter
+public class CDataConditioner extends XmlAdapter<String, String> implements AttributeConverter<String, String> {
+
+    private static final String NL = "\n";
+
+    @Override
+    public String convertToDatabaseColumn(final String raw) {
+        return clean(raw);
+    }
+
+    @Override
+    public String convertToEntityAttribute(final String db) {
+        return clean(db);
+    }
+
+    @Override
+    public String unmarshal(final String value) throws Exception {
+        return this.convertToEntityAttribute(value);
+    }
+
+    @Override
+    public String marshal(final String value) throws Exception {
+        return this.convertToDatabaseColumn(value);
+    }
+
+    /**
+     * Clean.
+     *
+     * @param in the in
+     * @return the string
+     */
+    public static final String clean(final String in) {
+        if (in == null) {
+            return null;
+        } else {
+            return in.replaceAll("\\s+$", "").replaceAll("\\r?\\n", NL);
+        }
+    }
+}
diff --git a/models-dao/src/main/java/org/onap/policy/models/dao/converters/Uuid2String.java b/models-dao/src/main/java/org/onap/policy/models/dao/converters/Uuid2String.java
new file mode 100644
index 0000000..a2b1c08
--- /dev/null
+++ b/models-dao/src/main/java/org/onap/policy/models/dao/converters/Uuid2String.java
@@ -0,0 +1,60 @@
+/*-
+ * ============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.dao.converters;
+
+import java.util.UUID;
+
+import javax.persistence.AttributeConverter;
+import javax.persistence.Converter;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+/**
+ * The Class UUIDConverter converts a UUID to and from database format.
+ */
+@Converter
+public class Uuid2String extends XmlAdapter<String, UUID> implements AttributeConverter<UUID, String> {
+
+    @Override
+    public String convertToDatabaseColumn(final UUID uuid) {
+        String returnString;
+        if (uuid == null) {
+            returnString = "";
+        } else {
+            returnString = uuid.toString();
+        }
+        return returnString;
+    }
+
+    @Override
+    public UUID convertToEntityAttribute(final String uuidString) {
+        return UUID.fromString(uuidString);
+    }
+
+    @Override
+    public UUID unmarshal(final String value) throws Exception {
+        return this.convertToEntityAttribute(value);
+    }
+
+    @Override
+    public String marshal(final UUID value) throws Exception {
+        return this.convertToDatabaseColumn(value);
+    }
+}
diff --git a/models-dao/src/main/java/org/onap/policy/models/dao/converters/package-info.java b/models-dao/src/main/java/org/onap/policy/models/dao/converters/package-info.java
new file mode 100644
index 0000000..416eff2
--- /dev/null
+++ b/models-dao/src/main/java/org/onap/policy/models/dao/converters/package-info.java
@@ -0,0 +1,26 @@
+/*-
+ * ============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=========================================================
+ */
+
+/**
+ * Contains converters used by PF EclipseLink marshaling and unmarshaling of
+ * {@link org.onap.policy.models.base.PfConcept} instances to and from files and databases.
+ */
+
+package org.onap.policy.models.dao.converters;
diff --git a/models-dao/src/main/java/org/onap/policy/models/dao/impl/DefaultPfDao.java b/models-dao/src/main/java/org/onap/policy/models/dao/impl/DefaultPfDao.java
new file mode 100644
index 0000000..429632d
--- /dev/null
+++ b/models-dao/src/main/java/org/onap/policy/models/dao/impl/DefaultPfDao.java
@@ -0,0 +1,415 @@
+/*-
+ * ============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.dao.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+
+import org.onap.policy.models.base.PfConcept;
+import org.onap.policy.models.base.PfConceptKey;
+import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.base.PfModelRuntimeException;
+import org.onap.policy.models.base.PfReferenceKey;
+import org.onap.policy.models.dao.DaoParameters;
+import org.onap.policy.models.dao.PfDao;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The Class DefaultPfDao is an JPA implementation of the {@link PfDao} class for Policy Framework
+ * concepts ({@link PfConcept}). It uses the default JPA implementation in the javax
+ * {@link Persistence} class.
+ */
+public class DefaultPfDao implements PfDao {
+    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultPfDao.class);
+
+    private static final String SELECT_C_FROM = "SELECT c FROM ";
+    private static final String AND_C_KEY_LOCAL_NAME = "' AND c.key.localName='";
+    private static final String AND_C_KEY_PARENT_KEY_VERSION = "' AND c.key.parentKeyVersion='";
+    private static final String C_WHERE_C_KEY_PARENT_KEY_NAME = " c WHERE c.key.parentKeyName='";
+    private static final String AND_C_KEY_VERSION = "' AND c.key.version='";
+    private static final String C_WHERE_C_KEY_NAME = " c WHERE c.key.name='";
+    private static final String DELETE_FROM = "DELETE FROM ";
+
+    // Entity manager for JPA
+    private EntityManagerFactory emf = null;
+
+    @Override
+    public void init(final DaoParameters daoParameters) throws PfModelException {
+        if (daoParameters == null || daoParameters.getPersistenceUnit() == null) {
+            LOGGER.error("Policy Framework persistence unit parameter not set");
+            throw new PfModelException("Policy Framework persistence unit parameter not set");
+        }
+
+        LOGGER.debug("Creating Policy Framework persistence unit \"{}\" . . .", daoParameters.getPersistenceUnit());
+        try {
+            emf = Persistence.createEntityManagerFactory(daoParameters.getPersistenceUnit(),
+                    daoParameters.getJdbcProperties());
+        } catch (final Exception ex) {
+            String errorMessage = "Creation of Policy Framework persistence unit \""
+                    + daoParameters.getPersistenceUnit() + "\" failed";
+            LOGGER.warn(errorMessage, ex);
+            throw new PfModelException(errorMessage, ex);
+        }
+        LOGGER.debug("Created Policy Framework persistence unit \"{}\"", daoParameters.getPersistenceUnit());
+    }
+
+    /**
+     * Gets the entity manager for this DAO.
+     *
+     * @return the entity manager
+     */
+    protected final synchronized EntityManager getEntityManager() {
+        if (emf == null) {
+            LOGGER.warn("Policy Framework DAO has not been initialized");
+            throw new PfModelRuntimeException("Policy Framework DAO has not been initialized");
+        }
+
+        return emf.createEntityManager();
+    }
+
+    @Override
+    public final void close() {
+        if (emf != null) {
+            emf.close();
+        }
+    }
+
+    @Override
+    public <T extends PfConcept> void create(final T obj) {
+        if (obj == null) {
+            return;
+        }
+        final EntityManager mg = getEntityManager();
+        try {
+            mg.getTransaction().begin();
+            mg.merge(obj);
+            mg.getTransaction().commit();
+        } finally {
+            mg.close();
+        }
+    }
+
+    @Override
+    public <T extends PfConcept> void delete(final T obj) {
+        if (obj == null) {
+            return;
+        }
+        final EntityManager mg = getEntityManager();
+        try {
+            mg.getTransaction().begin();
+            mg.remove(mg.contains(obj) ? obj : mg.merge(obj));
+            mg.getTransaction().commit();
+        } finally {
+            mg.close();
+        }
+    }
+
+    @Override
+    public <T extends PfConcept> void delete(final Class<T> someClass, final PfConceptKey key) {
+        if (key == null) {
+            return;
+        }
+        final EntityManager mg = getEntityManager();
+        try {
+            mg.getTransaction().begin();
+            mg.createQuery(DELETE_FROM + someClass.getSimpleName() + C_WHERE_C_KEY_NAME + key.getName()
+                    + AND_C_KEY_VERSION + key.getVersion() + "'", someClass).executeUpdate();
+            mg.getTransaction().commit();
+        } finally {
+            mg.close();
+        }
+    }
+
+    @Override
+    public <T extends PfConcept> void delete(final Class<T> someClass, final PfReferenceKey key) {
+        if (key == null) {
+            return;
+        }
+        final EntityManager mg = getEntityManager();
+        try {
+            mg.getTransaction().begin();
+            mg.createQuery(DELETE_FROM + someClass.getSimpleName() + C_WHERE_C_KEY_PARENT_KEY_NAME
+                    + key.getParentKeyName() + AND_C_KEY_PARENT_KEY_VERSION + key.getParentKeyVersion()
+                    + AND_C_KEY_LOCAL_NAME + key.getLocalName() + "'", someClass).executeUpdate();
+            mg.getTransaction().commit();
+        } finally {
+            mg.close();
+        }
+    }
+
+    @Override
+    public <T extends PfConcept> void createCollection(final Collection<T> objs) {
+        if (objs == null || objs.isEmpty()) {
+            return;
+        }
+        final EntityManager mg = getEntityManager();
+        try {
+            mg.getTransaction().begin();
+            for (final T t : objs) {
+                mg.merge(t);
+            }
+            mg.getTransaction().commit();
+        } finally {
+            mg.close();
+        }
+    }
+
+    @Override
+    public <T extends PfConcept> void deleteCollection(final Collection<T> objs) {
+        if (objs == null || objs.isEmpty()) {
+            return;
+        }
+        final EntityManager mg = getEntityManager();
+        try {
+            mg.getTransaction().begin();
+            for (final T t : objs) {
+                mg.remove(mg.contains(t) ? t : mg.merge(t));
+            }
+            mg.getTransaction().commit();
+        } finally {
+            mg.close();
+        }
+    }
+
+    @Override
+    public <T extends PfConcept> int deleteByConceptKey(final Class<T> someClass,
+            final Collection<PfConceptKey> keys) {
+        if (keys == null || keys.isEmpty()) {
+            return 0;
+        }
+        int deletedCount = 0;
+        final EntityManager mg = getEntityManager();
+        try {
+            mg.getTransaction().begin();
+            for (final PfConceptKey key : keys) {
+                deletedCount += mg.createQuery(DELETE_FROM + someClass.getSimpleName() + C_WHERE_C_KEY_NAME
+                        + key.getName() + AND_C_KEY_VERSION + key.getVersion() + "'", someClass).executeUpdate();
+            }
+            mg.getTransaction().commit();
+        } finally {
+            mg.close();
+        }
+        return deletedCount;
+    }
+
+    @Override
+    public <T extends PfConcept> int deleteByReferenceKey(final Class<T> someClass,
+            final Collection<PfReferenceKey> keys) {
+        if (keys == null || keys.isEmpty()) {
+            return 0;
+        }
+        int deletedCount = 0;
+        final EntityManager mg = getEntityManager();
+        try {
+            mg.getTransaction().begin();
+            for (final PfReferenceKey key : keys) {
+                deletedCount +=
+                        mg.createQuery(
+                                DELETE_FROM + someClass.getSimpleName() + C_WHERE_C_KEY_PARENT_KEY_NAME
+                                        + key.getParentKeyName() + AND_C_KEY_PARENT_KEY_VERSION
+                                        + key.getParentKeyVersion() + AND_C_KEY_LOCAL_NAME + key.getLocalName() + "'",
+                                someClass).executeUpdate();
+            }
+            mg.getTransaction().commit();
+        } finally {
+            mg.close();
+        }
+        return deletedCount;
+    }
+
+    @Override
+    public <T extends PfConcept> void deleteAll(final Class<T> someClass) {
+        final EntityManager mg = getEntityManager();
+        try {
+            mg.getTransaction().begin();
+            mg.createQuery(DELETE_FROM + someClass.getSimpleName() + " c ", someClass).executeUpdate();
+            mg.getTransaction().commit();
+        } finally {
+            mg.close();
+        }
+    }
+
+    @Override
+    public <T extends PfConcept> T get(final Class<T> someClass, final PfConceptKey key) {
+        if (someClass == null) {
+            return null;
+        }
+        final EntityManager mg = getEntityManager();
+        try {
+            final T t = mg.find(someClass, key);
+            if (t != null) {
+                // This clone is created to force the JPA DAO to recurse down through the object
+                try {
+                    final T clonedT = someClass.newInstance();
+                    t.copyTo(clonedT);
+                    return clonedT;
+                } catch (final Exception e) {
+                    LOGGER.warn("Could not clone object of class \"" + someClass.getCanonicalName() + "\"", e);
+                    return null;
+                }
+            } else {
+                return null;
+            }
+        } finally {
+            mg.close();
+        }
+    }
+
+    @Override
+    public <T extends PfConcept> T get(final Class<T> someClass, final PfReferenceKey key) {
+        if (someClass == null) {
+            return null;
+        }
+        final EntityManager mg = getEntityManager();
+        try {
+            final T t = mg.find(someClass, key);
+            if (t != null) {
+                try {
+                    final T clonedT = someClass.newInstance();
+                    t.copyTo(clonedT);
+                    return clonedT;
+                } catch (final Exception e) {
+                    LOGGER.warn("Could not clone object of class \"" + someClass.getCanonicalName() + "\"", e);
+                    return null;
+                }
+            } else {
+                return null;
+            }
+        } finally {
+            mg.close();
+        }
+    }
+
+    @Override
+    public <T extends PfConcept> List<T> getAll(final Class<T> someClass) {
+        if (someClass == null) {
+            return Collections.emptyList();
+        }
+        final EntityManager mg = getEntityManager();
+        try {
+            return mg.createQuery(SELECT_C_FROM + someClass.getSimpleName() + " c", someClass).getResultList();
+        } finally {
+            mg.close();
+        }
+    }
+
+    @Override
+    public <T extends PfConcept> List<T> getAll(final Class<T> someClass, final PfConceptKey parentKey) {
+        if (someClass == null) {
+            return Collections.emptyList();
+        }
+        final EntityManager mg = getEntityManager();
+        try {
+            return mg
+                    .createQuery(
+                            SELECT_C_FROM + someClass.getSimpleName() + C_WHERE_C_KEY_PARENT_KEY_NAME
+                                    + parentKey.getName() + AND_C_KEY_PARENT_KEY_VERSION + parentKey.getVersion() + "'",
+                            someClass)
+                    .getResultList();
+        } finally {
+            mg.close();
+        }
+    }
+
+    @Override
+    public <T extends PfConcept> T getConcept(final Class<T> someClass, final PfConceptKey key) {
+        if (someClass == null || key == null) {
+            return null;
+        }
+        final EntityManager mg = getEntityManager();
+        List<T> ret;
+        try {
+            ret = mg.createQuery(SELECT_C_FROM + someClass.getSimpleName() + C_WHERE_C_KEY_NAME + key.getName()
+                    + AND_C_KEY_VERSION + key.getVersion() + "'", someClass).getResultList();
+        } finally {
+            mg.close();
+        }
+        if (ret == null || ret.isEmpty()) {
+            return null;
+        }
+        if (ret.size() > 1) {
+            throw new IllegalArgumentException("More than one result was returned for search for " + someClass
+                    + " with key " + key.getId() + ": " + ret);
+        }
+        return ret.get(0);
+    }
+
+    @Override
+    public <T extends PfConcept> T getConcept(final Class<T> someClass, final PfReferenceKey key) {
+        if (someClass == null || key == null) {
+            return null;
+        }
+        final EntityManager mg = getEntityManager();
+        List<T> ret;
+        try {
+            ret = mg.createQuery(SELECT_C_FROM + someClass.getSimpleName() + C_WHERE_C_KEY_PARENT_KEY_NAME
+                    + key.getParentKeyName() + AND_C_KEY_PARENT_KEY_VERSION + key.getParentKeyVersion()
+                    + AND_C_KEY_LOCAL_NAME + key.getLocalName() + "'", someClass).getResultList();
+        } finally {
+            mg.close();
+        }
+        if (ret == null || ret.isEmpty()) {
+            return null;
+        }
+        if (ret.size() > 1) {
+            throw new IllegalArgumentException("More than one result was returned for search for " + someClass
+                    + " with key " + key.getId() + ": " + ret);
+        }
+        return ret.get(0);
+    }
+
+    @Override
+    public <T extends PfConcept> T update(final T obj) {
+        final EntityManager mg = getEntityManager();
+        T ret;
+        try {
+            mg.getTransaction().begin();
+            ret = mg.merge(obj);
+            mg.flush();
+            mg.getTransaction().commit();
+        } finally {
+            mg.close();
+        }
+        return ret;
+    }
+
+    @Override
+    public <T extends PfConcept> long size(final Class<T> someClass) {
+        if (someClass == null) {
+            return 0;
+        }
+        final EntityManager mg = getEntityManager();
+        long size = 0;
+        try {
+            size = mg.createQuery("SELECT COUNT(c) FROM " + someClass.getSimpleName() + " c", Long.class)
+                    .getSingleResult();
+        } finally {
+            mg.close();
+        }
+        return size;
+    }
+}
diff --git a/models-dao/src/main/java/org/onap/policy/models/dao/impl/package-info.java b/models-dao/src/main/java/org/onap/policy/models/dao/impl/package-info.java
new file mode 100644
index 0000000..0d27628
--- /dev/null
+++ b/models-dao/src/main/java/org/onap/policy/models/dao/impl/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * ============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=========================================================
+ */
+
+/**
+ * Contains a default DAO implementation for the PF {@link org.onap.policy.models.base.PfConcept}
+ * classes that uses javax persistence.
+ */
+package org.onap.policy.models.dao.impl;
diff --git a/models-dao/src/main/java/org/onap/policy/models/dao/package-info.java b/models-dao/src/main/java/org/onap/policy/models/dao/package-info.java
new file mode 100644
index 0000000..e8cfbe4
--- /dev/null
+++ b/models-dao/src/main/java/org/onap/policy/models/dao/package-info.java
@@ -0,0 +1,27 @@
+/*-
+ * ============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=========================================================
+ */
+
+/**
+ * Defines and implements the Data Access Object (DAO) that allows Apex
+ * {@link org.onap.policy.apex.model.basicmodel.concepts.AxConcept} concepts to be read from and written to databases
+ * over JDBC.
+ */
+
+package org.onap.policy.models.dao;
diff --git a/models-dao/src/test/java/org/onap/policy/models/dao/DaoMiscTest.java b/models-dao/src/test/java/org/onap/policy/models/dao/DaoMiscTest.java
new file mode 100644
index 0000000..4dd70ce
--- /dev/null
+++ b/models-dao/src/test/java/org/onap/policy/models/dao/DaoMiscTest.java
@@ -0,0 +1,89 @@
+/*-
+ * ============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.dao;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.util.Properties;
+
+import org.junit.Test;
+import org.onap.policy.models.dao.DaoParameters;
+import org.onap.policy.models.dao.PfDaoFactory;
+import org.onap.policy.models.dao.converters.CDataConditioner;
+import org.onap.policy.models.dao.converters.Uuid2String;
+
+public class DaoMiscTest {
+
+    @Test
+    public void testUuid2StringMopUp() {
+        final Uuid2String uuid2String = new Uuid2String();
+        assertEquals("", uuid2String.convertToDatabaseColumn(null));
+    }
+
+    @Test
+    public void testCDataConditionerMopUp() {
+        assertNull(CDataConditioner.clean(null));
+    }
+
+    @Test
+    public void testDaoFactory() {
+        final DaoParameters daoParameters = new DaoParameters();
+
+        daoParameters.setPluginClass("somewhere.over.the.rainbow");
+        try {
+            new PfDaoFactory().createPfDao(daoParameters);
+            fail("test shold throw an exception here");
+        } catch (final Exception e) {
+            assertEquals("Policy Framework DAO class not found for DAO plugin \"somewhere.over.the.rainbow\"",
+                    e.getMessage());
+        }
+
+        daoParameters.setPluginClass("java.lang.String");
+        try {
+            new PfDaoFactory().createPfDao(daoParameters);
+            fail("test shold throw an exception here");
+        } catch (final Exception e) {
+            assertEquals("Specified DAO plugin class \"java.lang.String\" " + "does not implement the PfDao interface",
+                    e.getMessage());
+        }
+    }
+
+    @Test
+    public void testDaoParameters() {
+        final DaoParameters pars = new DaoParameters();
+        pars.setJdbcProperties(new Properties());
+        assertEquals(0, pars.getJdbcProperties().size());
+
+        pars.setJdbcProperty("name", "Dorothy");
+        assertEquals("Dorothy", pars.getJdbcProperty("name"));
+
+        pars.setPersistenceUnit("Kansas");
+        assertEquals("Kansas", pars.getPersistenceUnit());
+
+        pars.setPluginClass("somewhere.over.the.rainbow");
+        assertEquals("somewhere.over.the.rainbow", pars.getPluginClass());
+
+        assertEquals("DAOParameters [pluginClass=somewhere.over.the.rainbow, "
+                + "persistenceUnit=Kansas, jdbcProperties={name=Dorothy}]", pars.toString());
+    }
+}
diff --git a/models-dao/src/test/java/org/onap/policy/models/dao/DummyConceptEntity.java b/models-dao/src/test/java/org/onap/policy/models/dao/DummyConceptEntity.java
new file mode 100644
index 0000000..fa2e71a
--- /dev/null
+++ b/models-dao/src/test/java/org/onap/policy/models/dao/DummyConceptEntity.java
@@ -0,0 +1,139 @@
+/*-
+ * ============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.dao;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NonNull;
+
+import org.onap.policy.common.utils.validation.Assertions;
+import org.onap.policy.models.base.PfConcept;
+import org.onap.policy.models.base.PfConceptKey;
+import org.onap.policy.models.base.PfKey;
+import org.onap.policy.models.base.PfValidationResult;
+
+@Entity
+@Table(name = "DummyConceptEntity")
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class DummyConceptEntity extends PfConcept {
+    private static final long serialVersionUID = -2962570563281067894L;
+
+    @EmbeddedId()
+    @NonNull
+    private PfConceptKey key;
+
+    @Column
+    @NonNull
+    private UUID uuid;
+
+    @Column
+    @NonNull
+    private String description;
+
+    public DummyConceptEntity() {
+        this.key = new PfConceptKey();
+    }
+
+    public DummyConceptEntity(final Double doubleValue) {
+        this.key = new PfConceptKey();
+    }
+
+    public DummyConceptEntity(final PfConceptKey key, final Double doubleValue) {
+        this.key = key;
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param key the key
+     * @param uuid the uuid
+     * @param description the description
+     */
+    public DummyConceptEntity(PfConceptKey key, UUID uuid, String description) {
+        this.key = key;
+        this.uuid = uuid;
+        this.description = description;
+    }
+
+    @Override
+    public List<PfKey> getKeys() {
+        final List<PfKey> keyList = new ArrayList<>();
+        keyList.add(getKey());
+        return keyList;
+    }
+
+    @Override
+    public PfValidationResult validate(final PfValidationResult result) {
+        return key.validate(result);
+    }
+
+    @Override
+    public void clean() {
+        key.clean();
+    }
+
+    @Override
+    public PfConcept copyTo(final PfConcept target) {
+        Assertions.argumentNotNull(target, "target may not be null");
+
+        final PfConcept copyObject = target;
+        Assertions.instanceOf(copyObject, DummyConceptEntity.class);
+
+        final DummyConceptEntity copy = ((DummyConceptEntity) copyObject);
+        copy.setKey(key);
+        copy.setUuid(uuid);
+        copy.setDescription(description);
+
+        return copyObject;
+    }
+
+    @Override
+    public int compareTo(final PfConcept otherObj) {
+        Assertions.argumentNotNull(otherObj, "comparison object may not be null");
+
+        if (this == otherObj) {
+            return 0;
+        }
+        if (getClass() != otherObj.getClass()) {
+            return this.hashCode() - otherObj.hashCode();
+        }
+
+        final DummyConceptEntity other = (DummyConceptEntity) otherObj;
+
+        if (!key.equals(other.key)) {
+            return key.compareTo(other.key);
+        }
+        if (!uuid.equals(other.uuid)) {
+            return uuid.compareTo(other.uuid);
+        }
+        return description.compareTo(other.description);
+    }
+}
diff --git a/models-dao/src/test/java/org/onap/policy/models/dao/DummyReferenceEntity.java b/models-dao/src/test/java/org/onap/policy/models/dao/DummyReferenceEntity.java
new file mode 100644
index 0000000..044a63d
--- /dev/null
+++ b/models-dao/src/test/java/org/onap/policy/models/dao/DummyReferenceEntity.java
@@ -0,0 +1,121 @@
+/*-
+ * ============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.dao;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.Table;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NonNull;
+
+import org.onap.policy.common.utils.validation.Assertions;
+import org.onap.policy.models.base.PfConcept;
+import org.onap.policy.models.base.PfKey;
+import org.onap.policy.models.base.PfReferenceKey;
+import org.onap.policy.models.base.PfValidationResult;
+
+@Entity
+@Table(name = "DummyReferenceEntity")
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class DummyReferenceEntity extends PfConcept {
+    private static final long serialVersionUID = -2962570563281067894L;
+
+    @EmbeddedId()
+    @NonNull
+    private PfReferenceKey key;
+
+    @Column
+    private double doubleValue;
+
+    /**
+     * Default constructor.
+     */
+    public DummyReferenceEntity() {
+        this.key = new PfReferenceKey();
+        this.doubleValue = 123.45;
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param key the key
+     * @param doubleValue the double value
+     */
+    public DummyReferenceEntity(final PfReferenceKey key, final double doubleValue) {
+        this.key = key;
+        this.doubleValue = doubleValue;
+    }
+
+    @Override
+    public List<PfKey> getKeys() {
+        final List<PfKey> keyList = new ArrayList<>();
+        keyList.add(getKey());
+        return keyList;
+    }
+
+    @Override
+    public PfValidationResult validate(final PfValidationResult result) {
+        return key.validate(result);
+    }
+
+    @Override
+    public void clean() {
+        key.clean();
+    }
+
+    @Override
+    public PfConcept copyTo(final PfConcept target) {
+        Assertions.argumentNotNull(target, "target may not be null");
+
+        final PfConcept copyObject = target;
+        Assertions.instanceOf(copyObject, DummyReferenceEntity.class);
+
+        final DummyReferenceEntity copy = ((DummyReferenceEntity) copyObject);
+        copy.setKey(key);
+        copy.setDoubleValue(doubleValue);
+
+        return copyObject;
+    }
+
+
+    @Override
+    public int compareTo(final PfConcept otherObj) {
+        Assertions.argumentNotNull(otherObj, "comparison object may not be null");
+
+        if (this == otherObj) {
+            return 0;
+        }
+        if (getClass() != otherObj.getClass()) {
+            return this.hashCode() - otherObj.hashCode();
+        }
+
+        final DummyReferenceEntity other = (DummyReferenceEntity) otherObj;
+
+        return  new Double(doubleValue).compareTo(new Double(other.doubleValue));
+    }
+}
diff --git a/models-dao/src/test/java/org/onap/policy/models/dao/EntityTest.java b/models-dao/src/test/java/org/onap/policy/models/dao/EntityTest.java
new file mode 100644
index 0000000..8278cfe
--- /dev/null
+++ b/models-dao/src/test/java/org/onap/policy/models/dao/EntityTest.java
@@ -0,0 +1,299 @@
+/*-
+ * ============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.dao;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.models.base.PfConceptKey;
+import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.base.PfReferenceKey;
+import org.onap.policy.models.dao.DaoParameters;
+import org.onap.policy.models.dao.PfDao;
+import org.onap.policy.models.dao.PfDaoFactory;
+import org.onap.policy.models.dao.impl.DefaultPfDao;
+
+/**
+ * JUnit test class.
+ */
+public class EntityTest {
+    private Connection connection;
+    private PfDao pfDao;
+
+    @Before
+    public void setup() throws Exception {
+        connection = DriverManager.getConnection("jdbc:h2:mem:test");
+    }
+
+    @After
+    public void teardown() throws Exception {
+        connection.close();
+        new File("derby.log").delete();
+    }
+
+    @Test
+    public void testEntityTestSanity() throws PfModelException {
+        final DaoParameters daoParameters = new DaoParameters();
+
+        pfDao = new PfDaoFactory().createPfDao(daoParameters);
+
+        try {
+            pfDao.init(null);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals("Policy Framework persistence unit parameter not set", e.getMessage());
+        }
+
+        try {
+            pfDao.init(daoParameters);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals("Policy Framework persistence unit parameter not set", e.getMessage());
+        }
+
+        daoParameters.setPluginClass("somewhere.over.the.rainbow");
+        daoParameters.setPersistenceUnit("Dorothy");
+        try {
+            pfDao.init(daoParameters);
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals("Creation of Policy Framework persistence unit \"Dorothy\" failed", e.getMessage());
+        }
+        try {
+            pfDao.create(new PfConceptKey());
+            fail("Test should throw an exception here");
+        } catch (final Exception e) {
+            assertEquals("Policy Framework DAO has not been initialized", e.getMessage());
+        }
+        pfDao.close();
+    }
+
+    @Test
+    public void testEntityTestAllOpsJpa() throws PfModelException {
+        final DaoParameters daoParameters = new DaoParameters();
+        daoParameters.setPluginClass(DefaultPfDao.class.getCanonicalName());
+        daoParameters.setPersistenceUnit("DaoTest");
+
+        pfDao = new PfDaoFactory().createPfDao(daoParameters);
+        pfDao.init(daoParameters);
+
+        testAllOps();
+        pfDao.close();
+    }
+
+    @Test
+    public void testEntityTestBadVals() throws PfModelException {
+        final DaoParameters daoParameters = new DaoParameters();
+        daoParameters.setPluginClass(DefaultPfDao.class.getCanonicalName());
+        daoParameters.setPersistenceUnit("DaoTest");
+
+        pfDao = new PfDaoFactory().createPfDao(daoParameters);
+        pfDao.init(daoParameters);
+
+        final PfConceptKey nullKey = null;
+        final PfReferenceKey nullRefKey = null;
+        final List<PfConceptKey> nullKeyList = null;
+        final List<PfConceptKey> emptyKeyList = new ArrayList<>();
+        final List<PfReferenceKey> nullRKeyList = null;
+        final List<PfReferenceKey> emptyRKeyList = new ArrayList<>();
+
+        pfDao.create(nullKey);
+        pfDao.createCollection(nullKeyList);
+        pfDao.createCollection(emptyKeyList);
+
+        pfDao.delete(nullKey);
+        pfDao.deleteCollection(nullKeyList);
+        pfDao.deleteCollection(emptyKeyList);
+        pfDao.delete(PfConceptKey.class, nullKey);
+        pfDao.delete(PfReferenceKey.class, nullRefKey);
+        pfDao.deleteByConceptKey(PfConceptKey.class, nullKeyList);
+        pfDao.deleteByConceptKey(PfConceptKey.class, emptyKeyList);
+        pfDao.deleteByReferenceKey(PfReferenceKey.class, nullRKeyList);
+        pfDao.deleteByReferenceKey(PfReferenceKey.class, emptyRKeyList);
+
+        pfDao.get(null, nullKey);
+        pfDao.get(null, nullRefKey);
+        pfDao.getAll(null);
+        pfDao.getAll(null, nullKey);
+        pfDao.getConcept(null, nullKey);
+        pfDao.getConcept(PfConceptKey.class, nullKey);
+        pfDao.getConcept(null, nullRefKey);
+        pfDao.getConcept(PfReferenceKey.class, nullRefKey);
+        pfDao.size(null);
+
+        pfDao.close();
+    }
+
+    private void testAllOps() {
+        final PfConceptKey aKey0 = new PfConceptKey("A-KEY0", "0.0.1");
+        final PfConceptKey aKey1 = new PfConceptKey("A-KEY1", "0.0.1");
+        final PfConceptKey aKey2 = new PfConceptKey("A-KEY2", "0.0.1");
+        final DummyConceptEntity keyInfo0 = new DummyConceptEntity(aKey0,
+                UUID.fromString("00000000-0000-0000-0000-000000000000"), "key description 0");
+        final DummyConceptEntity keyInfo1 = new DummyConceptEntity(aKey1,
+                UUID.fromString("00000000-0000-0000-0000-000000000001"), "key description 1");
+        final DummyConceptEntity keyInfo2 = new DummyConceptEntity(aKey2,
+                UUID.fromString("00000000-0000-0000-0000-000000000002"), "key description 2");
+
+        pfDao.create(keyInfo0);
+
+        final DummyConceptEntity keyInfoBack0 = pfDao.get(DummyConceptEntity.class, aKey0);
+        assertTrue(keyInfo0.equals(keyInfoBack0));
+
+        final DummyConceptEntity keyInfoBackNull = pfDao.get(DummyConceptEntity.class, PfConceptKey.getNullKey());
+        assertNull(keyInfoBackNull);
+
+        final DummyConceptEntity keyInfoBack1 = pfDao.getConcept(DummyConceptEntity.class, aKey0);
+        assertTrue(keyInfoBack0.equals(keyInfoBack1));
+
+        final DummyConceptEntity keyInfoBack2 =
+                pfDao.getConcept(DummyConceptEntity.class, new PfConceptKey("A-KEY3", "0.0.1"));
+        assertNull(keyInfoBack2);
+
+        final Set<DummyConceptEntity> keyInfoSetIn = new TreeSet<DummyConceptEntity>();
+        keyInfoSetIn.add(keyInfo1);
+        keyInfoSetIn.add(keyInfo2);
+
+        pfDao.createCollection(keyInfoSetIn);
+
+        Set<DummyConceptEntity> keyInfoSetOut = new TreeSet<DummyConceptEntity>(pfDao.getAll(DummyConceptEntity.class));
+
+        keyInfoSetIn.add(keyInfo0);
+        assertTrue(keyInfoSetIn.equals(keyInfoSetOut));
+
+        pfDao.delete(keyInfo1);
+        keyInfoSetIn.remove(keyInfo1);
+        keyInfoSetOut = new TreeSet<DummyConceptEntity>(pfDao.getAll(DummyConceptEntity.class));
+        assertTrue(keyInfoSetIn.equals(keyInfoSetOut));
+
+        pfDao.deleteCollection(keyInfoSetIn);
+        keyInfoSetOut = new TreeSet<DummyConceptEntity>(pfDao.getAll(DummyConceptEntity.class));
+        assertEquals(0, keyInfoSetOut.size());
+
+        keyInfoSetIn.add(keyInfo0);
+        keyInfoSetIn.add(keyInfo1);
+        keyInfoSetIn.add(keyInfo0);
+        pfDao.createCollection(keyInfoSetIn);
+        keyInfoSetOut = new TreeSet<DummyConceptEntity>(pfDao.getAll(DummyConceptEntity.class));
+        assertTrue(keyInfoSetIn.equals(keyInfoSetOut));
+
+        pfDao.delete(DummyConceptEntity.class, aKey0);
+        keyInfoSetOut = new TreeSet<DummyConceptEntity>(pfDao.getAll(DummyConceptEntity.class));
+        assertEquals(2, keyInfoSetOut.size());
+        assertEquals(2, pfDao.size(DummyConceptEntity.class));
+
+        final Set<PfConceptKey> keySetIn = new TreeSet<PfConceptKey>();
+        keySetIn.add(aKey1);
+        keySetIn.add(aKey2);
+
+        final int deletedCount = pfDao.deleteByConceptKey(DummyConceptEntity.class, keySetIn);
+        assertEquals(2, deletedCount);
+
+        keyInfoSetOut = new TreeSet<DummyConceptEntity>(pfDao.getAll(DummyConceptEntity.class));
+        assertEquals(0, keyInfoSetOut.size());
+
+        keyInfoSetIn.add(keyInfo0);
+        keyInfoSetIn.add(keyInfo1);
+        keyInfoSetIn.add(keyInfo0);
+        pfDao.createCollection(keyInfoSetIn);
+        keyInfoSetOut = new TreeSet<DummyConceptEntity>(pfDao.getAll(DummyConceptEntity.class));
+        assertTrue(keyInfoSetIn.equals(keyInfoSetOut));
+
+        pfDao.deleteAll(DummyConceptEntity.class);
+        assertEquals(0, pfDao.size(DummyConceptEntity.class));
+
+        final PfConceptKey owner0Key = new PfConceptKey("Owner0", "0.0.1");
+        final PfConceptKey owner1Key = new PfConceptKey("Owner1", "0.0.1");
+        final PfConceptKey owner2Key = new PfConceptKey("Owner2", "0.0.1");
+        final PfConceptKey owner3Key = new PfConceptKey("Owner3", "0.0.1");
+        final PfConceptKey owner4Key = new PfConceptKey("Owner4", "0.0.1");
+        final PfConceptKey owner5Key = new PfConceptKey("Owner5", "0.0.1");
+
+        pfDao.create(new DummyReferenceEntity(new PfReferenceKey(owner0Key, "Entity0"), 100.0));
+        pfDao.create(new DummyReferenceEntity(new PfReferenceKey(owner0Key, "Entity1"), 101.0));
+        pfDao.create(new DummyReferenceEntity(new PfReferenceKey(owner0Key, "Entity2"), 102.0));
+        pfDao.create(new DummyReferenceEntity(new PfReferenceKey(owner0Key, "Entity3"), 103.0));
+        pfDao.create(new DummyReferenceEntity(new PfReferenceKey(owner0Key, "Entity4"), 104.0));
+        pfDao.create(new DummyReferenceEntity(new PfReferenceKey(owner1Key, "Entity5"), 105.0));
+        pfDao.create(new DummyReferenceEntity(new PfReferenceKey(owner1Key, "Entity6"), 106.0));
+        pfDao.create(new DummyReferenceEntity(new PfReferenceKey(owner1Key, "Entity7"), 107.0));
+        pfDao.create(new DummyReferenceEntity(new PfReferenceKey(owner2Key, "Entity8"), 108.0));
+        pfDao.create(new DummyReferenceEntity(new PfReferenceKey(owner2Key, "Entity9"), 109.0));
+        pfDao.create(new DummyReferenceEntity(new PfReferenceKey(owner3Key, "EntityA"), 110.0));
+        pfDao.create(new DummyReferenceEntity(new PfReferenceKey(owner4Key, "EntityB"), 111.0));
+        pfDao.create(new DummyReferenceEntity(new PfReferenceKey(owner5Key, "EntityC"), 112.0));
+        pfDao.create(new DummyReferenceEntity(new PfReferenceKey(owner5Key, "EntityD"), 113.0));
+        pfDao.create(new DummyReferenceEntity(new PfReferenceKey(owner5Key, "EntityE"), 114.0));
+        pfDao.create(new DummyReferenceEntity(new PfReferenceKey(owner5Key, "EntityF"), 115.0));
+
+        TreeSet<DummyReferenceEntity> testEntitySetOut =
+                new TreeSet<DummyReferenceEntity>(pfDao.getAll(DummyReferenceEntity.class));
+        assertEquals(16, testEntitySetOut.size());
+
+        testEntitySetOut = new TreeSet<DummyReferenceEntity>(pfDao.getAll(DummyReferenceEntity.class, owner0Key));
+        assertEquals(5, testEntitySetOut.size());
+
+        testEntitySetOut = new TreeSet<DummyReferenceEntity>(pfDao.getAll(DummyReferenceEntity.class, owner1Key));
+        assertEquals(3, testEntitySetOut.size());
+
+        testEntitySetOut = new TreeSet<DummyReferenceEntity>(pfDao.getAll(DummyReferenceEntity.class, owner2Key));
+        assertEquals(2, testEntitySetOut.size());
+
+        testEntitySetOut = new TreeSet<DummyReferenceEntity>(pfDao.getAll(DummyReferenceEntity.class, owner3Key));
+        assertEquals(1, testEntitySetOut.size());
+
+        testEntitySetOut = new TreeSet<DummyReferenceEntity>(pfDao.getAll(DummyReferenceEntity.class, owner4Key));
+        assertEquals(1, testEntitySetOut.size());
+
+        testEntitySetOut = new TreeSet<DummyReferenceEntity>(pfDao.getAll(DummyReferenceEntity.class, owner5Key));
+        assertEquals(4, testEntitySetOut.size());
+
+        assertNotNull(pfDao.get(DummyReferenceEntity.class, new PfReferenceKey(owner0Key, "Entity0")));
+        assertNotNull(pfDao.getConcept(DummyReferenceEntity.class, new PfReferenceKey(owner0Key, "Entity0")));
+        assertNull(pfDao.get(DummyReferenceEntity.class, new PfReferenceKey(owner0Key, "Entity1000")));
+        assertNull(pfDao.getConcept(DummyReferenceEntity.class, new PfReferenceKey(owner0Key, "Entity1000")));
+        pfDao.delete(DummyReferenceEntity.class, new PfReferenceKey(owner0Key, "Entity0"));
+
+        final Set<PfReferenceKey> rKeySetIn = new TreeSet<PfReferenceKey>();
+        rKeySetIn.add(new PfReferenceKey(owner4Key, "EntityB"));
+        rKeySetIn.add(new PfReferenceKey(owner5Key, "EntityD"));
+
+        final int deletedRCount = pfDao.deleteByReferenceKey(DummyReferenceEntity.class, rKeySetIn);
+        assertEquals(2, deletedRCount);
+
+        pfDao.update(new DummyReferenceEntity(new PfReferenceKey(owner5Key, "EntityF"), 120.0));
+    }
+}
diff --git a/models-dao/src/test/resources/META-INF/persistence.xml b/models-dao/src/test/resources/META-INF/persistence.xml
new file mode 100644
index 0000000..1f430bc
--- /dev/null
+++ b/models-dao/src/test/resources/META-INF/persistence.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ============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=========================================================
+-->
+
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
+    <persistence-unit name="DaoTest" transaction-type="RESOURCE_LOCAL">
+        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+
+        <class>org.onap.policy.models.dao.converters.CDataConditioner</class>
+        <class>org.onap.policy.models.dao.converters.Uuid2String</class>
+        <class>org.onap.policy.models.base.concepts.PfConcepttKey</class>
+        <class>org.onap.policy.models.dao.DummyConceptEntity</class>
+        <class>org.onap.policy.models.dao.DummyReferenceEntity</class>
+
+        <properties>
+            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
+            <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:testdb" />
+            <property name="javax.persistence.jdbc.user" value="sa" />
+            <property name="javax.persistence.jdbc.password" value="" />
+            <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
+            <property name="eclipselink.ddl-generation.output-mode" value="database" />
+            <property name="eclipselink.logging.level" value="INFO" />
+        </properties>
+    </persistence-unit>
+</persistence>
diff --git a/models-dao/src/test/resources/logback-test.xml b/models-dao/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..f0c510c
--- /dev/null
+++ b/models-dao/src/test/resources/logback-test.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ============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=========================================================
+-->
+
+<configuration>
+
+    <contextName>PolicyModels</contextName>
+    <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
+    <property name="LOG_DIR" value="${java.io.tmpdir}/onap_policy_logging/" />
+
+    <!-- USE FOR STD OUT ONLY -->
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <Pattern>%d %contextName [%t] %level %logger{36} - %msg%n</Pattern>
+        </encoder>
+    </appender>
+
+    <root level="INFO">
+        <appender-ref ref="STDOUT" />
+    </root>
+
+    <logger name="org.infinispan" level="INFO" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <logger name="org.apache.zookeeper.ClientCnxn" level="OFF" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+
+    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+        <file>${LOG_DIR}/models.log</file>
+        <encoder>
+            <pattern>%d %-5relative [procId=${processId}] [%thread] %-5level
+                %logger{26} - %msg %n %ex{full}</pattern>
+        </encoder>
+    </appender>
+
+    <logger name="org.onap.policy.models.dao" level="INFO" additivity="false">
+        <appender-ref ref="STDOUT" />
+    </logger>
+</configuration>