diff options
Diffstat (limited to 'models-dao/src')
4 files changed, 292 insertions, 55 deletions
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 index 85c971ce7..609afefd4 100644 --- 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 @@ -29,8 +29,8 @@ 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. + * 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 { @@ -108,7 +108,7 @@ public interface PfDao { <T extends PfConcept> int deleteByConceptKey(Class<T> someClass, Collection<PfConceptKey> keys); /** - * Delete a collection of objects in the database referred to by reference key. + * policypolicypolicy 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} @@ -129,6 +129,18 @@ public interface PfDao { * 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}, if name is null, all concepts + * of type T are returned, if name is not null and version is null, all versions of that concept matching the + * name are returned. + * @param key the key of the object to get + * @return the objects that was retrieved from the database + */ + <T extends PfConcept> List<T> getFiltered(Class<T> someClass, PfConceptKey key); + + /** + * 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 @@ -141,8 +153,7 @@ public interface PfDao { * @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 + * @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); @@ -166,6 +177,35 @@ public interface PfDao { <T extends PfConcept> List<T> getAll(Class<T> someClass, PfConceptKey parentKey); /** + * 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} + * @param name the name of the concepts for which to get all versions + * @return the objects or null if no objects were retrieved + */ + <T extends PfConcept> List<T> getAllVersions(Class<T> someClass, final String name); + + /** + * Get latest version of 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> getLatestVersions(Class<T> someClass); + + /** + * Get latest version of an object 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} + * @param conceptName the name of the concept for which to get the latest version + * @return the objects or null if no objects were retrieved + */ + <T extends PfConcept> T getLatestVersion(Class<T> someClass, final String conceptName); + + /** * 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} @@ -197,7 +237,7 @@ public interface PfDao { /** * Update a concept in the database. * - * @param <T> the type of the object to get, a subclass of {@link PfConcept} + * @param <T> the type of the object to update, a subclass of {@link PfConcept} * @param obj the object to update * @return the updated object */ 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 index 947b866a1..f7659b2ce 100644 --- 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 @@ -40,20 +40,58 @@ 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. + * 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 "; + // @formatter:off + private static final String NAME = "name"; + private static final String VERSION = "version"; + private static final String PARENT_NAME = "parentname"; + private static final String PARENT_VERSION = "parentversion"; + private static final String LOCAL_NAME = "localname"; + + private static final String TABLE_TOKEN = "__TABLE__"; + + private static final String DELETE_FROM_TABLE = "DELETE FROM __TABLE__ c"; + + private static final String SELECT_FROM_TABLE = "SELECT c FROM __TABLE__ c"; + + private static final String WHERE = " WHERE "; + private static final String AND = " AND "; + + private static final String NAME_FILTER = "c.key.name = :name"; + private static final String VERSION_FILTER = "c.key.version = :version"; + private static final String PARENT_NAME_FILTER = "c.key.parentKeyName = :parentname"; + private static final String PARENT_VERSION_FILTER = "c.key.parentKeyVersion = :parentversion"; + private static final String LOCAL_NAME_FILTER = "c.key.localName = :localname"; + private static final String MAX_VERISON_FILTER = "c.key.version = (SELECT MAX(c.key.version) FROM __TABLE__ c)"; + + private static final String DELETE_BY_CONCEPT_KEY = + DELETE_FROM_TABLE + WHERE + NAME_FILTER + AND + VERSION_FILTER; + + private static final String DELETE_BY_REFERENCE_KEY = + DELETE_FROM_TABLE + WHERE + PARENT_NAME_FILTER + AND + PARENT_VERSION_FILTER + AND + LOCAL_NAME_FILTER; + + private static final String SELECT_ALL_FOR_PARENT = + SELECT_FROM_TABLE + WHERE + PARENT_NAME_FILTER + AND + PARENT_VERSION_FILTER; + + private static final String SELECT_ALL_VERSIONS = SELECT_FROM_TABLE + WHERE + NAME_FILTER; + + private static final String SELECT_LATEST_VERSION = + SELECT_FROM_TABLE + WHERE + NAME_FILTER + AND + MAX_VERISON_FILTER; + + private static final String SELECT_LATEST_VERSIONS = + "SELECT c FROM __TABLE__ c WHERE c.key.version = (SELECT MAX(c.key.version) FROM __TABLE__ c)"; + + private static final String SELECT_BY_CONCEPT_KEY = + SELECT_FROM_TABLE + WHERE + NAME_FILTER + AND + VERSION_FILTER; + + private static final String SELECT_BY_REFERENCE_KEY = + SELECT_FROM_TABLE + WHERE + PARENT_NAME_FILTER + AND + PARENT_VERSION_FILTER + AND + LOCAL_NAME_FILTER; + // @formatter:on // Entity manager for JPA private EntityManagerFactory emf = null; @@ -138,10 +176,14 @@ public class DefaultPfDao implements PfDao { } final EntityManager mg = getEntityManager(); try { + // @formatter:off 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.createQuery(setQueryTable(DELETE_BY_CONCEPT_KEY, someClass), someClass) + .setParameter(NAME, key.getName()) + .setParameter("version", key.getVersion()) + .executeUpdate(); mg.getTransaction().commit(); + // @formatter:on } finally { mg.close(); } @@ -154,11 +196,15 @@ public class DefaultPfDao implements PfDao { } final EntityManager mg = getEntityManager(); try { + // @formatter:off 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.createQuery(setQueryTable(DELETE_BY_REFERENCE_KEY, someClass), someClass) + .setParameter(PARENT_NAME, key.getParentKeyName()) + .setParameter(PARENT_VERSION, key.getParentKeyVersion()) + .setParameter(LOCAL_NAME, key.getLocalName()) + .executeUpdate(); mg.getTransaction().commit(); + // @formatter:on } finally { mg.close(); } @@ -206,12 +252,16 @@ public class DefaultPfDao implements PfDao { int deletedCount = 0; final EntityManager mg = getEntityManager(); try { + // @formatter:off 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(); + deletedCount += mg.createQuery(setQueryTable(DELETE_BY_CONCEPT_KEY, someClass), someClass) + .setParameter(NAME, key.getName()) + .setParameter("version", key.getVersion()) + .executeUpdate(); } mg.getTransaction().commit(); + // @formatter:on } finally { mg.close(); } @@ -227,16 +277,17 @@ public class DefaultPfDao implements PfDao { int deletedCount = 0; final EntityManager mg = getEntityManager(); try { + // @formatter:off 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(); + deletedCount += mg.createQuery(setQueryTable(DELETE_BY_REFERENCE_KEY, someClass), someClass) + .setParameter(PARENT_NAME, key.getParentKeyName()) + .setParameter(PARENT_VERSION, key.getParentKeyVersion()) + .setParameter(LOCAL_NAME, key.getLocalName()) + .executeUpdate(); } mg.getTransaction().commit(); + // @formatter:on } finally { mg.close(); } @@ -248,7 +299,7 @@ public class DefaultPfDao implements PfDao { final EntityManager mg = getEntityManager(); try { mg.getTransaction().begin(); - mg.createQuery(DELETE_FROM + someClass.getSimpleName() + " c ", someClass).executeUpdate(); + mg.createQuery(setQueryTable(DELETE_FROM_TABLE, someClass), someClass).executeUpdate(); mg.getTransaction().commit(); } finally { mg.close(); @@ -256,6 +307,21 @@ public class DefaultPfDao implements PfDao { } @Override + public <T extends PfConcept> List<T> getFiltered(Class<T> someClass, PfConceptKey key) { + if (key.getName() == null) { + return getAll(someClass); + } + + if (key.getVersion() == null) { + return getAllVersions(someClass, key.getName()); + } + + T foundConcept = get(someClass, key); + + return (foundConcept == null ? Collections.emptyList() : Collections.singletonList(foundConcept)); + } + + @Override public <T extends PfConcept> T get(final Class<T> someClass, final PfConceptKey key) { if (someClass == null) { return null; @@ -313,7 +379,7 @@ public class DefaultPfDao implements PfDao { } final EntityManager mg = getEntityManager(); try { - return mg.createQuery(SELECT_C_FROM + someClass.getSimpleName() + " c", someClass).getResultList(); + return mg.createQuery(setQueryTable(SELECT_FROM_TABLE, someClass), someClass).getResultList(); } finally { mg.close(); } @@ -326,62 +392,112 @@ public class DefaultPfDao implements PfDao { } 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) + // @formatter:off + return mg.createQuery(setQueryTable(SELECT_ALL_FOR_PARENT, someClass), someClass) + .setParameter(PARENT_NAME, parentKey.getName()) + .setParameter(PARENT_VERSION, parentKey.getVersion()) .getResultList(); + // @formatter:on } finally { mg.close(); } } @Override - public <T extends PfConcept> T getConcept(final Class<T> someClass, final PfConceptKey key) { - if (someClass == null || key == null) { - return null; + public <T extends PfConcept> List<T> getAllVersions(final Class<T> someClass, final String conceptName) { + if (someClass == null || conceptName == null) { + return Collections.emptyList(); + } + final EntityManager mg = getEntityManager(); + try { + // @formatter:off + return mg.createQuery(setQueryTable(SELECT_ALL_VERSIONS, someClass), someClass) + .setParameter(NAME, conceptName) + .getResultList(); + // @formatter:on + } finally { + mg.close(); + } + } + + @Override + public <T extends PfConcept> List<T> getLatestVersions(final Class<T> someClass) { + if (someClass == null) { + return Collections.emptyList(); } 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(); + // @formatter:off + return mg.createQuery(setQueryTable(SELECT_LATEST_VERSIONS, someClass), someClass) + .getResultList(); + // @formatter:on } finally { mg.close(); } - if (ret == null || ret.isEmpty()) { + } + + @Override + public <T extends PfConcept> T getLatestVersion(final Class<T> someClass, final String conceptName) { + if (someClass == null || conceptName == null) { return null; } - if (ret.size() > 1) { - throw new IllegalArgumentException("More than one result was returned for search for " + someClass - + " with key " + key.getId() + ": " + ret); + final EntityManager mg = getEntityManager(); + List<T> ret; + try { + // @formatter:off + ret = mg.createQuery(setQueryTable(SELECT_LATEST_VERSION, someClass), someClass) + .setParameter(NAME, conceptName) + .getResultList(); + // @formatter:on + } finally { + mg.close(); } - return ret.get(0); + + return getSingleResult(someClass, conceptName, ret); } @Override - public <T extends PfConcept> T getConcept(final Class<T> someClass, final PfReferenceKey key) { + 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_PARENT_KEY_NAME - + key.getParentKeyName() + AND_C_KEY_PARENT_KEY_VERSION + key.getParentKeyVersion() - + AND_C_KEY_LOCAL_NAME + key.getLocalName() + "'", someClass).getResultList(); + // @formatter:off + ret = mg.createQuery(setQueryTable(SELECT_BY_CONCEPT_KEY, someClass), someClass) + .setParameter(NAME, key.getName()) + .setParameter(VERSION, key.getVersion()) + .getResultList(); + // @formatter:on } finally { mg.close(); } - if (ret == null || ret.isEmpty()) { + + return getSingleResult(someClass, key.getId(), ret); + } + + @Override + public <T extends PfConcept> T getConcept(final Class<T> someClass, final PfReferenceKey key) { + if (someClass == null || key == null) { return null; } - if (ret.size() > 1) { - throw new IllegalArgumentException("More than one result was returned for search for " + someClass - + " with key " + key.getId() + ": " + ret); + final EntityManager mg = getEntityManager(); + List<T> ret; + try { + // @formatter:off + ret = mg.createQuery(setQueryTable(SELECT_BY_REFERENCE_KEY, someClass), someClass) + .setParameter(PARENT_NAME, key.getParentKeyName()) + .setParameter(PARENT_VERSION, key.getParentKeyVersion()) + .setParameter(LOCAL_NAME, key.getLocalName()) + .getResultList(); + // @formatter:on + } finally { + mg.close(); } - return ret.get(0); + + return getSingleResult(someClass, key.getId(), ret); } @Override @@ -414,4 +530,34 @@ public class DefaultPfDao implements PfDao { } return size; } + + /** + * Add the table to a query string. + * + * @param queryString the query string + * @param tableClass the class name of the table + * @return the updated query string + */ + private <T extends PfConcept> String setQueryTable(final String queryString, final Class<T> tableClass) { + return queryString.replaceAll(TABLE_TOKEN, tableClass.getSimpleName()); + } + + /** + * Check that a query returned one and only one entry and return that entry. + * + * @param someClass the class being searched for + * @param conceptName the concept name being searched for + * @param resultList the result list returned by the query + * @return the single unique result + */ + private <T extends PfConcept> T getSingleResult(final Class<T> someClass, final String searchFilter, List<T> ret) { + if (ret == null || ret.isEmpty()) { + return null; + } + if (ret.size() > 1) { + throw new IllegalArgumentException("More than one result was returned query on " + someClass + + " with filter " + searchFilter + ": " + ret); + } + return ret.get(0); + } } 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 index 9b07dfbb1..a0ad5c21d 100644 --- 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 @@ -109,6 +109,9 @@ public class EntityTest { pfDao.init(daoParameters); testAllOps(); + + testVersionOps(); + pfDao.close(); } @@ -294,4 +297,40 @@ public class EntityTest { pfDao.update(new DummyReferenceEntity(new PfReferenceKey(owner5Key, "EntityF"), 120.0)); } + + private void testVersionOps() { + final PfConceptKey aKey0 = new PfConceptKey("AAA0", "0.0.1"); + final PfConceptKey aKey1 = new PfConceptKey("AAA0", "0.0.2"); + final PfConceptKey aKey2 = new PfConceptKey("AAA0", "0.0.3"); + final PfConceptKey bKey0 = new PfConceptKey("BBB0", "0.0.1"); + final PfConceptKey bKey1 = new PfConceptKey("BBB0", "0.0.2"); + final PfConceptKey bKey2 = new PfConceptKey("BBB0", "0.0.3"); + 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"); + final DummyConceptEntity keyInfo3 = new DummyConceptEntity(bKey0, + UUID.fromString("00000000-0000-0000-0000-000000000000"), "key description 0"); + final DummyConceptEntity keyInfo4 = new DummyConceptEntity(bKey1, + UUID.fromString("00000000-0000-0000-0000-000000000001"), "key description 1"); + final DummyConceptEntity keyInfo5 = new DummyConceptEntity(bKey2, + UUID.fromString("00000000-0000-0000-0000-000000000002"), "key description 2"); + + pfDao.create(keyInfo0); + pfDao.create(keyInfo1); + pfDao.create(keyInfo2); + pfDao.create(keyInfo3); + pfDao.create(keyInfo4); + pfDao.create(keyInfo5); + + assertEquals(3, pfDao.getAllVersions(DummyConceptEntity.class, "AAA0").size()); + DummyConceptEntity latestVersionEntity = pfDao.getLatestVersion(DummyConceptEntity.class, "AAA0"); + assertEquals(aKey2, latestVersionEntity.getKey()); + List<DummyConceptEntity> returnedLatestVersions = pfDao.getLatestVersions(DummyConceptEntity.class); + assertEquals(2, returnedLatestVersions.size()); + assertEquals("0.0.3", returnedLatestVersions.get(0).getKey().getVersion()); + assertEquals("0.0.3", returnedLatestVersions.get(1).getKey().getVersion()); + } } diff --git a/models-dao/src/test/resources/META-INF/persistence.xml b/models-dao/src/test/resources/META-INF/persistence.xml index 5779deb18..25858caba 100644 --- a/models-dao/src/test/resources/META-INF/persistence.xml +++ b/models-dao/src/test/resources/META-INF/persistence.xml @@ -37,6 +37,18 @@ <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" /> + + <property name="eclipselink.logging.level" value="ALL" /> + <property name="eclipselink.logging.level.jpa" value="ALL" /> + <property name="eclipselink.logging.level.ddl" value="ALL" /> + <property name="eclipselink.logging.level.connection" value="ALL" /> + <property name="eclipselink.logging.level.sql" value="ALL" /> + <property name="eclipselink.logging.level.transaction" value="ALL" /> + <property name="eclipselink.logging.level.sequencing" value="ALL" /> + <property name="eclipselink.logging.level.server" value="ALL" /> + <property name="eclipselink.logging.level.query" value="ALL" /> + <property name="eclipselink.logging.level.properties" value="ALL" /> + </properties> </persistence-unit> </persistence> |