diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamDate.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamDate.java index cbfa191ff95..03a092566a4 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamDate.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamDate.java @@ -30,7 +30,6 @@ import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.hibernate.search.annotations.Field; import org.hl7.fhir.r4.model.DateTimeType; -import org.hl7.fhir.r4.model.InstantType; import javax.persistence.*; import java.util.Date; @@ -93,12 +92,20 @@ public class ResourceIndexedSearchParamDate extends BaseResourceIndexedSearchPar ResourceIndexedSearchParamDate obj = (ResourceIndexedSearchParamDate) theObj; EqualsBuilder b = new EqualsBuilder(); b.append(getParamName(), obj.getParamName()); + b.append(getResource(), obj.getResource()); - b.append(getValueHigh(), obj.getValueHigh()); - b.append(getValueLow(), obj.getValueLow()); + b.append(getTimeFromDate(getValueHigh()), getTimeFromDate(obj.getValueHigh())); + b.append(getTimeFromDate(getValueLow()), getTimeFromDate(obj.getValueLow())); return b.isEquals(); } + protected Long getTimeFromDate(Date date) { + if (date != null) { + return date.getTime(); + } + return null; + } + @Override protected Long getId() { return myId; @@ -125,8 +132,8 @@ public class ResourceIndexedSearchParamDate extends BaseResourceIndexedSearchPar HashCodeBuilder b = new HashCodeBuilder(); b.append(getParamName()); b.append(getResource()); - b.append(getValueHigh()); - b.append(getValueLow()); + b.append(getTimeFromDate(getValueHigh())); + b.append(getTimeFromDate(getValueLow())); return b.toHashCode(); } diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamDateTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamDateTest.java new file mode 100644 index 00000000000..3ddbe995ef5 --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/entity/ResourceIndexedSearchParamDateTest.java @@ -0,0 +1,117 @@ +package ca.uhn.fhir.jpa.entity; + +import org.junit.Before; +import org.junit.Test; + +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.Date; + +import static org.junit.Assert.*; + +public class ResourceIndexedSearchParamDateTest { + + private Date date1A, date1B, date2A, date2B; + private Timestamp timestamp1A, timestamp1B, timestamp2A, timestamp2B; + + @Before + public void setUp() throws Exception { + Calendar cal1 = Calendar.getInstance(); + cal1.set(1970, 01, 01, 10, 23, 33); + + Calendar cal2 = Calendar.getInstance(); + cal2.set(1990, 01, 01, 5, 11, 0); + + date1A = cal1.getTime(); + date1B = cal1.getTime(); + date2A = cal2.getTime(); + date2B = cal2.getTime(); + + timestamp1A = new Timestamp(date1A.getTime()); + timestamp1B = new Timestamp(date1B.getTime()); + timestamp2A = new Timestamp(date2A.getTime()); + timestamp2B = new Timestamp(date2B.getTime()); + } + + @Test + public void equalsIsTrueForMatchingNullDates() { + ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("SomeResource", null, null, "SomeValue"); + ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("SomeResource", null, null, "SomeValue"); + + assertTrue(param.equals(param2)); + assertTrue(param2.equals(param)); + assertEquals(param.hashCode(), param2.hashCode()); + } + + @Test + public void equalsIsTrueForMatchingDates() { + ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("SomeResource", date1A, date2A, "SomeValue"); + ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("SomeResource", date1B, date2B, "SomeValue"); + + assertTrue(param.equals(param2)); + assertTrue(param2.equals(param)); + assertEquals(param.hashCode(), param2.hashCode()); + } + + @Test + public void equalsIsTrueForMatchingTimeStampsThatMatch() { + ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("SomeResource", timestamp1A, timestamp2A, "SomeValue"); + ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("SomeResource", timestamp1B, timestamp2B, "SomeValue"); + + assertTrue(param.equals(param2)); + assertTrue(param2.equals(param)); + assertEquals(param.hashCode(), param2.hashCode()); + } + + // Scenario that occurs when updating a resource with a date search parameter. One date will be a java.util.Date, the + // other will be equivalent but will be a java.sql.Timestamp. Equals should work in both directions. + @Test + public void equalsIsTrueForMixedTimestampsAndDates() { + ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("SomeResource", date1A, date2A, "SomeValue"); + ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("SomeResource", timestamp1A, timestamp2A, "SomeValue"); + + assertTrue(param.equals(param2)); + assertTrue(param2.equals(param)); + assertEquals(param.hashCode(), param2.hashCode()); + } + + @Test + public void equalsIsFalseForNonMatchingDates() { + ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("SomeResource", date1A, date2A, "SomeValue"); + ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("SomeResource", date2A, date1A, "SomeValue"); + + assertFalse(param.equals(param2)); + assertFalse(param2.equals(param)); + assertNotEquals(param.hashCode(), param2.hashCode()); + } + + @Test + public void equalsIsFalseForNonMatchingDatesNullCase() { + ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("SomeResource", date1A, date2A, "SomeValue"); + ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("SomeResource", null, null, "SomeValue"); + + assertFalse(param.equals(param2)); + assertFalse(param2.equals(param)); + assertNotEquals(param.hashCode(), param2.hashCode()); + } + + @Test + public void equalsIsFalseForNonMatchingTimeStamps() { + ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("SomeResource", timestamp1A, timestamp2A, "SomeValue"); + ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("SomeResource", timestamp2A, timestamp1A, "SomeValue"); + + assertFalse(param.equals(param2)); + assertFalse(param2.equals(param)); + assertNotEquals(param.hashCode(), param2.hashCode()); + } + + @Test + public void equalsIsFalseForMixedTimestampsAndDatesThatDoNotMatch() { + ResourceIndexedSearchParamDate param = new ResourceIndexedSearchParamDate("SomeResource", date1A, date2A, "SomeValue"); + ResourceIndexedSearchParamDate param2 = new ResourceIndexedSearchParamDate("SomeResource", timestamp2A, timestamp1A, "SomeValue"); + + assertFalse(param.equals(param2)); + assertFalse(param2.equals(param)); + assertNotEquals(param.hashCode(), param2.hashCode()); + } +}