From: rameshiyer27 Date: Mon, 1 Mar 2021 18:46:33 +0000 (+0000) Subject: Fix Reference Key columns persistence issue in db X-Git-Tag: 2.4.1~5 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=fcbf3698fa3e3fbc6ea3364d80d4a3f3a8d37650;p=policy%2Fmodels.git Fix Reference Key columns persistence issue in db Problem: When PfReferenceTimestamp Key is persisted in db, the parent class fields are ignored which causes inconsistent data while saving and fetching in db. Fix: JPA is not supporting inheritance in @Embeddable classes. Hence included the super class as @Embedded property in PfReferenceTimestamp key. @Embedded properties are unable to be queried directly. Slightly modified Dao methods to support querying @embedded fields. Issue-ID: POLICY-3049 Signed-off-by: zrrmmua Change-Id: I5c2e03a5ae98525764a64dd6cce1a1298c5f9816 --- diff --git a/models-base/src/main/java/org/onap/policy/models/base/PfReferenceTimestampKey.java b/models-base/src/main/java/org/onap/policy/models/base/PfReferenceTimestampKey.java index 47a72e8cd..06af688b0 100644 --- a/models-base/src/main/java/org/onap/policy/models/base/PfReferenceTimestampKey.java +++ b/models-base/src/main/java/org/onap/policy/models/base/PfReferenceTimestampKey.java @@ -22,12 +22,14 @@ package org.onap.policy.models.base; import java.sql.Timestamp; import java.time.Instant; +import java.util.Collections; +import java.util.List; import javax.persistence.Column; import javax.persistence.Embeddable; +import javax.persistence.Embedded; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NonNull; -import lombok.ToString; import org.onap.policy.common.parameters.annotations.NotNull; import org.onap.policy.common.utils.validation.Assertions; @@ -36,11 +38,11 @@ import org.onap.policy.common.utils.validation.Assertions; * additional option to have timestamp as a parameter. * */ + @Embeddable @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class PfReferenceTimestampKey extends PfReferenceKey { +@EqualsAndHashCode +public class PfReferenceTimestampKey extends PfKey { private static final long serialVersionUID = 1130918285832617215L; private static final String TIMESTAMP_TOKEN = "timeStamp"; @@ -49,24 +51,27 @@ public class PfReferenceTimestampKey extends PfReferenceKey { @NotNull private Timestamp timeStamp; + @Embedded + @Column + private PfReferenceKey referenceKey; /** * The default constructor creates a null reference timestamp key. */ public PfReferenceTimestampKey() { - super(); + this.referenceKey = new PfReferenceKey(); this.timeStamp = new Timestamp(0); } /** * The Copy Constructor creates a key by copying another key. * - * @param referenceKey + * @param referenceTimestampKey * the reference key to copy from */ - public PfReferenceTimestampKey(final PfReferenceTimestampKey referenceKey) { - super(referenceKey); - this.timeStamp = referenceKey.getTimeStamp(); + public PfReferenceTimestampKey(final PfReferenceTimestampKey referenceTimestampKey) { + this.referenceKey = referenceTimestampKey.getReferenceKey(); + this.timeStamp = referenceTimestampKey.getTimeStamp(); } /** @@ -76,7 +81,7 @@ public class PfReferenceTimestampKey extends PfReferenceKey { * the parent concept key of this reference key */ public PfReferenceTimestampKey(final PfConceptKey pfConceptKey) { - super(pfConceptKey); + this.referenceKey = new PfReferenceKey(pfConceptKey); this.timeStamp = new Timestamp(0); } @@ -91,7 +96,7 @@ public class PfReferenceTimestampKey extends PfReferenceKey { * the time stamp for this reference key */ public PfReferenceTimestampKey(final PfConceptKey pfConceptKey, final String localName, final Instant instant) { - super(pfConceptKey, localName); + this.referenceKey = new PfReferenceKey(pfConceptKey, localName); this.timeStamp = Timestamp.from(instant); } @@ -107,7 +112,7 @@ public class PfReferenceTimestampKey extends PfReferenceKey { */ public PfReferenceTimestampKey(final PfReferenceKey parentReferenceKey, final String localName, final Instant instant) { - super(parentReferenceKey, localName); + this.referenceKey = new PfReferenceKey(parentReferenceKey, localName); this.timeStamp = Timestamp.from(instant); } @@ -126,7 +131,7 @@ public class PfReferenceTimestampKey extends PfReferenceKey { */ public PfReferenceTimestampKey(final PfConceptKey pfConceptKey, final String parentLocalName, final String localName, final Instant instant) { - super(pfConceptKey, parentLocalName, localName); + this.referenceKey = new PfReferenceKey(pfConceptKey, parentLocalName, localName); this.timeStamp = Timestamp.from(instant); } @@ -145,7 +150,7 @@ public class PfReferenceTimestampKey extends PfReferenceKey { */ public PfReferenceTimestampKey(final String parentKeyName, final String parentKeyVersion, final String localName, final Instant instant) { - super(parentKeyName, parentKeyVersion, NULL_KEY_NAME, localName); + this.referenceKey = new PfReferenceKey(parentKeyName, parentKeyVersion, PfKey.NULL_KEY_NAME, localName); this.timeStamp = Timestamp.from(instant); } @@ -166,7 +171,7 @@ public class PfReferenceTimestampKey extends PfReferenceKey { */ public PfReferenceTimestampKey(final String parentKeyName, final String parentKeyVersion, final String parentLocalName, final String localName, final Instant instant) { - super(parentKeyName, parentKeyVersion, parentLocalName, localName); + this.referenceKey = new PfReferenceKey(parentKeyName, parentKeyVersion, parentLocalName, localName); this.timeStamp = Timestamp.from(instant); } @@ -177,7 +182,7 @@ public class PfReferenceTimestampKey extends PfReferenceKey { * @param id the key ID in a format that respects the KEY_ID_REGEXP */ public PfReferenceTimestampKey(final String id) { - super(id.substring(0, id.lastIndexOf(':'))); + this.referenceKey = new PfReferenceKey(id.substring(0, id.lastIndexOf(':'))); this.timeStamp = new Timestamp(Long.parseLong(id.substring(id.lastIndexOf(':') + 1))); } @@ -200,32 +205,99 @@ public class PfReferenceTimestampKey extends PfReferenceKey { setTimeStamp(Timestamp.from(instant)); } - @Override + /** + * Get the key of this reference. + * + * @return the pfReferenceTimestamp key + */ public PfReferenceTimestampKey getKey() { return this; } - @Override + /** + * Get the key as a string. + * @return pfReferenceTimestamp key. + */ public String getId() { - return super.getId() + ':' + getTimeStamp().getTime(); + return getReferenceKey().getId() + ':' + getTimeStamp().getTime(); + } + + + /** + * Check if this key is a newer version than the other key. + * + * @param otherKey the key to check against + * @return true, if this key is newer than the other key + */ + @Override + public boolean isNewerThan(@NonNull PfKey otherKey) { + Assertions.instanceOf(otherKey, PfReferenceTimestampKey.class); + final PfReferenceTimestampKey otherReferenceKey = (PfReferenceTimestampKey) otherKey; + if (!getTimeStamp().equals(otherReferenceKey.timeStamp)) { + return timeStamp.after(otherReferenceKey.timeStamp); + } + return getReferenceKey().isNewerThan(otherReferenceKey.getReferenceKey()); } @Override public boolean isNullKey() { - return super.isNullKey() && getTimeStamp().getTime() == 0; + return getReferenceKey().isNullKey() && getTimeStamp().getTime() == 0; } @Override - public boolean isNewerThan(@NonNull PfKey otherKey) { - Assertions.instanceOf(otherKey, PfReferenceTimestampKey.class); - final PfReferenceTimestampKey otherConceptKey = (PfReferenceTimestampKey) otherKey; + public int getMajorVersion() { + return getReferenceKey().getMajorVersion(); + } - if (this.equals(otherConceptKey)) { - return false; + @Override + public int getMinorVersion() { + return getReferenceKey().getMinorVersion(); + } + + @Override + public int getPatchVersion() { + return getReferenceKey().getPatchVersion(); + } + + + @Override + public int compareTo(@NonNull final PfConcept otherObj) { + if (this == otherObj) { + return 0; + } + if (getClass() != otherObj.getClass()) { + return getClass().getName().compareTo(otherObj.getClass().getName()); } - if (!getTimeStamp().equals(otherConceptKey.timeStamp)) { - return timeStamp.after(otherConceptKey.timeStamp); + int result = getReferenceKey().compareTo(((PfReferenceTimestampKey) otherObj).getReferenceKey()); + if (0 == result) { + return getTimeStamp().compareTo(((PfReferenceTimestampKey) otherObj).timeStamp); } - return super.isNewerThan(otherKey); + return result; + } + + @Override + public List getKeys() { + return Collections.singletonList(getKey()); + } + + @Override + public void clean() { + getReferenceKey().clean(); + } + + @Override + public Compatibility getCompatibility(@NonNull PfKey otherKey) { + return getReferenceKey().getCompatibility(otherKey); + } + + @Override + public boolean isCompatible(@NonNull PfKey otherKey) { + if (!(otherKey instanceof PfReferenceTimestampKey)) { + return false; + } + final PfReferenceTimestampKey otherReferenceKey = (PfReferenceTimestampKey) otherKey; + + return this.getReferenceKey().getParentConceptKey().isCompatible(otherReferenceKey.getReferenceKey() + .getParentConceptKey()); } } diff --git a/models-base/src/test/java/org/onap/policy/models/base/PfReferenceTimestampKeyTest.java b/models-base/src/test/java/org/onap/policy/models/base/PfReferenceTimestampKeyTest.java index 061760aeb..12b9e3509 100644 --- a/models-base/src/test/java/org/onap/policy/models/base/PfReferenceTimestampKeyTest.java +++ b/models-base/src/test/java/org/onap/policy/models/base/PfReferenceTimestampKeyTest.java @@ -43,13 +43,14 @@ public class PfReferenceTimestampKeyTest { @Test public void testPfReferenceTimestampKeyConstruct() { - assertThat(new PfReferenceTimestampKey().getLocalName()).isEqualTo(PfKey.NULL_KEY_NAME); - assertEquals(PfKey.NULL_KEY_NAME, new PfReferenceTimestampKey(new PfConceptKey()).getParentKeyName()); + assertThat(new PfReferenceTimestampKey().getReferenceKey().getLocalName()).isEqualTo(PfKey.NULL_KEY_NAME); + assertEquals(PfKey.NULL_KEY_NAME, new PfReferenceTimestampKey(new PfConceptKey()).getReferenceKey() + .getParentKeyName()); assertNotNull(new PfReferenceTimestampKey(new PfReferenceTimestampKey()).getTimeStamp()); assertEquals(LOCAL_NAME, new PfReferenceTimestampKey(new PfReferenceKey(), LOCAL_NAME, Instant.ofEpochSecond(timeStamp)) - .getLocalName()); + .getReferenceKey().getLocalName()); assertEquals(Timestamp.from(Instant.ofEpochSecond(timeStamp)), new PfReferenceTimestampKey(new PfConceptKey(), PARENT_LOCAL_NAME, LOCAL_NAME, Instant.ofEpochSecond(timeStamp)).getTimeStamp()); @@ -58,7 +59,7 @@ public class PfReferenceTimestampKeyTest { assertThat( new PfReferenceTimestampKey("ParentKeyName", VERSION001, LOCAL_NAME, Instant.ofEpochSecond(timeStamp)) - .getParentLocalName()).isEqualTo(PfKey.NULL_KEY_NAME); + .getReferenceKey().getParentLocalName()).isEqualTo(PfKey.NULL_KEY_NAME); assertEquals(PfReferenceTimestampKey.getNullKey().getKey(), PfReferenceTimestampKey.getNullKey()); assertEquals("NULL:0.0.0:NULL:NULL:" + Instant.EPOCH.getEpochSecond(), @@ -67,9 +68,8 @@ public class PfReferenceTimestampKeyTest { assertThatThrownBy(() -> new PfReferenceTimestampKey(new PfConceptKey(), null, null)) .hasMessage("parameter \"localName\" is null"); - assertTrue(new PfReferenceTimestampKey().isNullKey()); - assertFalse(new PfReferenceTimestampKey("ParentKeyName", VERSION001, PfKey.NULL_KEY_NAME, - LOCAL_NAME, Instant.EPOCH).isNullKey()); + PfReferenceTimestampKey testNullKey = new PfReferenceTimestampKey(); + assertTrue(testNullKey.isNullKey()); String id = "NULL:0.0.0:NULL:NULL:" + timeStamp; assertThat(new PfReferenceTimestampKey(id).getTimeStamp().getTime()).isEqualTo(timeStamp); @@ -78,26 +78,26 @@ public class PfReferenceTimestampKeyTest { @Test public void testPfReferenceTimestampKey() { PfReferenceTimestampKey testReferenceKey = new PfReferenceTimestampKey(); - testReferenceKey.setParentConceptKey(new PfConceptKey("PN", VERSION001)); - assertEquals("PN:0.0.1", testReferenceKey.getParentConceptKey().getId()); + testReferenceKey.setReferenceKey(new PfReferenceKey(new PfConceptKey("PN", VERSION001))); + assertEquals("PN:0.0.1", testReferenceKey.getReferenceKey().getParentConceptKey().getId()); assertEquals(1, testReferenceKey.getKeys().size()); assertFalse(testReferenceKey.isNullKey()); - testReferenceKey.setParentReferenceKey(new PfReferenceKey("PN", VERSION001, "LN")); - assertEquals("PN:0.0.1:NULL:LN", testReferenceKey.getParentReferenceKey().getId()); + testReferenceKey.setReferenceKey(new PfReferenceKey("PN", VERSION001, "LN")); + assertEquals("PN:0.0.1:NULL:LN", testReferenceKey.getReferenceKey().getId()); - testReferenceKey.setParentKeyName("PKN"); - assertEquals("PKN", testReferenceKey.getParentKeyName()); + testReferenceKey.getReferenceKey().setParentKeyName("PKN"); + assertEquals("PKN", testReferenceKey.getReferenceKey().getParentKeyName()); - testReferenceKey.setParentKeyVersion(VERSION001); - assertEquals(VERSION001, testReferenceKey.getParentKeyVersion()); + testReferenceKey.getReferenceKey().setParentKeyVersion(VERSION001); + assertEquals(VERSION001, testReferenceKey.getReferenceKey().getParentKeyVersion()); - testReferenceKey.setParentLocalName(PARENT_LOCAL_NAME); - assertEquals(PARENT_LOCAL_NAME, testReferenceKey.getParentLocalName()); + testReferenceKey.getReferenceKey().setParentLocalName(PARENT_LOCAL_NAME); + assertEquals(PARENT_LOCAL_NAME, testReferenceKey.getReferenceKey().getParentLocalName()); - testReferenceKey.setLocalName("LN"); - assertEquals("LN", testReferenceKey.getLocalName()); + testReferenceKey.getReferenceKey().setLocalName("LN"); + assertEquals("LN", testReferenceKey.getReferenceKey().getLocalName()); testReferenceKey.setTimeStamp(Timestamp.from(DEFAULT_TIMESTAMP)); assertEquals(Timestamp.from(DEFAULT_TIMESTAMP), testReferenceKey.getTimeStamp()); @@ -116,22 +116,23 @@ public class PfReferenceTimestampKeyTest { PfReferenceTimestampKey clonedReferenceKey = new PfReferenceTimestampKey(testReferenceKey); - assertEquals("PfReferenceTimestampKey(super=PfReferenceKey(parentKeyName=PKN, parentKeyVersion=0.0.1, " - + "parentLocalName=ParentLocalName, localName=LN), timeStamp=" + Timestamp.from(Instant.EPOCH) + ")", - clonedReferenceKey.toString()); + assertEquals("PfReferenceTimestampKey(timeStamp=" + Timestamp.from(Instant.EPOCH) + "," + + " referenceKey=PfReferenceKey(parentKeyName=PKN, parentKeyVersion=0.0.1, " + + "parentLocalName=ParentLocalName, localName=LN))", clonedReferenceKey.toString()); assertNotEquals(0, testReferenceKey.hashCode()); assertEquals(testReferenceKey, clonedReferenceKey); - assertNotEquals(testReferenceKey, - new PfReferenceTimestampKey("PKN", VERSION001, "PLN", "LN", Instant.ofEpochSecond(timeStamp))); + assertNotEquals(testReferenceKey, new PfReferenceTimestampKey("PKN", VERSION001, "PLN", + "LN", Instant.ofEpochSecond(timeStamp))); testReferenceKey.setTimeStamp(Timestamp.from(Instant.ofEpochSecond(timeStamp))); assertEquals(testReferenceKey, new PfReferenceTimestampKey("PKN", VERSION001, PARENT_LOCAL_NAME, "LN", Instant.ofEpochSecond(timeStamp))); - assertNotEquals(0, testReferenceKey.compareTo(new PfConceptKey())); - assertNotEquals(0, testReferenceKey.compareTo( - new PfReferenceTimestampKey("PKN", VERSION002, "PLN", "LN", Instant.ofEpochSecond(timeStamp)))); + assertNotEquals(0, testReferenceKey.compareTo(new PfReferenceTimestampKey())); + assertNotEquals(0, testReferenceKey.compareTo(new PfReferenceTimestampKey("PKN", VERSION002, + "PLN", "LN", Instant.ofEpochSecond(timeStamp)))); + assertEquals(0, testReferenceKey.compareTo(new PfReferenceTimestampKey("PKN", VERSION001, PARENT_LOCAL_NAME, "LN", Instant.ofEpochSecond(timeStamp)))); 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 05f907fdd..eb77be9c0 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,6 +29,7 @@ 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; +import org.onap.policy.models.base.PfReferenceTimestampKey; import org.onap.policy.models.base.PfTimestampKey; /** @@ -201,6 +202,16 @@ public interface PfDao { */ T get(Class someClass, PfTimestampKey timestampKey); + /** + * Get an object from the database, referred to by reference timestamp key. + * + * @param 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 PfReferenceTimestampKey of the object to get + * @return the object that was retrieved from the database or null if the object was not retrieved + */ + T get(Class someClass, PfReferenceTimestampKey key); + /** * Get all the objects in the database of a given type. * 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 c29c4bf2d..ef86c177b 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 @@ -37,6 +37,7 @@ 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.base.PfReferenceTimestampKey; import org.onap.policy.models.base.PfTimestampKey; import org.onap.policy.models.base.PfUtils; import org.onap.policy.models.dao.DaoParameters; @@ -78,6 +79,8 @@ public class DefaultPfDao implements PfDao { 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 PARENT_NAME_REF_FILTER = "c.key.referenceKey.parentKeyName = :parentKeyName"; + private static final String CLONE_ERR_MSG = "Could not clone object of class \"{}\""; private static final String DELETE_BY_CONCEPT_KEY = @@ -366,7 +369,8 @@ public class DefaultPfDao implements PfDao { if (filterMap != null) { filterQueryString = buildFilter(filterMap, filterQueryString); } - filterQueryString = addKeyFilterString(filterQueryString, name, startTime, endTime); + filterQueryString = addKeyFilterString(filterQueryString, name, startTime, endTime, + isRefTimestampKey(someClass)); if (getRecordNum > 0) { filterQueryString += ORDER + " c.key.timeStamp " + sortOrder; } @@ -378,7 +382,11 @@ public class DefaultPfDao implements PfDao { } } if (name != null) { - query.setParameter("name", name); + if (isRefTimestampKey(someClass)) { + query.setParameter("parentKeyName", name); + } else { + query.setParameter("name", name); + } } if (startTime != null) { if (endTime != null) { @@ -398,11 +406,25 @@ public class DefaultPfDao implements PfDao { LOGGER.debug("filterQueryString is \"{}\"", filterQueryString); return query.getResultList(); - } finally { + } finally { mg.close(); } } + /** + * This method checks if the class invoking the DAO is using PfReferenceTimestamp Key. + * @param someClass class that invoked Dao + * @return true if the key is PfReferenceTimestampKey. + */ + private boolean isRefTimestampKey(final Class someClass) { + try { + return PfReferenceTimestampKey.class.isAssignableFrom(someClass.getDeclaredField("key").getType()); + } catch (NoSuchFieldException e) { + LOGGER.error("Error verifying the key for reference timestamp:", e); + return false; + } + } + private String buildFilter(final Map filterMap, String filterQueryString) { StringBuilder bld = new StringBuilder(filterQueryString); for (String key : filterMap.keySet()) { @@ -426,6 +448,11 @@ public class DefaultPfDao implements PfDao { return genericGet(someClass, key); } + @Override + public T get(final Class someClass, final PfReferenceTimestampKey key) { + return genericGet(someClass, key); + } + private T genericGet(final Class someClass, final Object key) { if (someClass == null) { return null; @@ -619,25 +646,31 @@ public class DefaultPfDao implements PfDao { * timeStamp <= endTime. null for ignore start time. * @param endTime the end timeStamp to filter from database, filter rule: startTime <= filteredRecord timeStamp <= * endTime. null for ignore end time + * @param isRefTimestampKey boolean value, set to true if the query invoked for pfReferenceTimestampKey * @return the filter string to query database */ private String addKeyFilterString(String inputFilterString, final String name, final Instant startTime, - final Instant endTime) { + final Instant endTime, final boolean isRefTimestampKey) { String filterQueryString; + String inputFilter = inputFilterString; if (name != null) { - inputFilterString += NAME_FILTER + AND; + if (isRefTimestampKey) { + inputFilter += PARENT_NAME_REF_FILTER + AND; + } else { + inputFilter += NAME_FILTER + AND; + } } if (startTime != null) { if (endTime != null) { - filterQueryString = inputFilterString + TIMESTAMP_START_FILTER + AND + TIMESTAMP_END_FILTER; + filterQueryString = inputFilter + TIMESTAMP_START_FILTER + AND + TIMESTAMP_END_FILTER; } else { - filterQueryString = inputFilterString + TIMESTAMP_START_FILTER; + filterQueryString = inputFilter + TIMESTAMP_START_FILTER; } } else { if (endTime != null) { - filterQueryString = inputFilterString + TIMESTAMP_END_FILTER; + filterQueryString = inputFilter + TIMESTAMP_END_FILTER; } else { - filterQueryString = inputFilterString.substring(0, inputFilterString.length() - AND.length()); + filterQueryString = inputFilter.substring(0, inputFilter.length() - AND.length()); } }