diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/DateRangeParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/DateRangeParam.java
index 8c164c37510..aa20383f423 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/DateRangeParam.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/DateRangeParam.java
@@ -215,6 +215,15 @@ public class DateRangeParam implements IQueryParameterAndge
* (greater than or equals) modifier.
*
+ * Note: An operation can take a DateRangeParam. If only a single date is provided,
+ * it will still result in a DateRangeParam where the lower and upper bounds
+ * are the same value. As such, even though the prefixes for the lower and
+ * upper bounds default to ge
and le
respectively,
+ * the resulting prefix is effectively eq
where only a single
+ * date is provided - as required by the FHIR specificiation (i.e. "If no
+ * prefix is present, the prefix eq
is assumed").
+ *
le
* (less than or equals) modifier.
*
+ *
+ * Note: An operation can take a DateRangeParam. If only a single date is provided,
+ * it will still result in a DateRangeParam where the lower and upper bounds
+ * are the same value. As such, even though the prefixes for the lower and
+ * upper bounds default to ge
and le
respectively,
+ * the resulting prefix is effectively eq
where only a single
+ * date is provided - as required by the FHIR specificiation (i.e. "If no
+ * prefix is present, the prefix eq
is assumed").
+ *
ge
and le
respectively,
+ * the resulting prefix is effectively eq
where only a single
+ * date is provided - as required by the FHIR specificiation (i.e. "If no
+ * prefix is present, the prefix eq
is assumed").
+ */
private void validateAndSet(DateParam lowerBound, DateParam upperBound) {
if (hasBound(lowerBound) && hasBound(upperBound)) {
if (lowerBound.getValue().getTime() > upperBound.getValue().getTime()) {
diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/param/DateRangeParamTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/param/DateRangeParamTest.java
index 72b03f5b4c9..6cfd86d3ad2 100644
--- a/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/param/DateRangeParamTest.java
+++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/rest/param/DateRangeParamTest.java
@@ -1,28 +1,209 @@
package ca.uhn.fhir.rest.param;
-import static org.junit.Assert.assertTrue;
-
-import java.util.ArrayList;
-import java.util.List;
-
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.api.QualifiedParamList;
-
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mockito;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import static ca.uhn.fhir.rest.param.ParamPrefixEnum.*;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
@RunWith(JUnit4.class)
public class DateRangeParamTest {
private FhirContext fhirContext;
+ private Date myBefore;
+ private Date myLower;
+ private Date myBetween;
+ private Date myUpper;
+ private Date myAfter;
+
+ @Rule
+ public final ExpectedException expectedException = ExpectedException.none();
@Before
public void initMockContext() {
fhirContext = Mockito.mock(FhirContext.class);
}
+ @Before
+ public void initDates() throws InterruptedException {
+ myBefore = new Date();
+ Thread.sleep(1L);
+ myLower = new Date();
+ Thread.sleep(1L);
+ myBetween = new Date();
+ Thread.sleep(1L);
+ myUpper = new Date();
+ Thread.sleep(1L);
+ myAfter = new Date();
+ }
+
+ @Test
+ public void testIsDateWithinRangeExclusive() {
+ DateParam lowerBound = new DateParam(GREATERTHAN, myLower);
+ DateParam upperBound = new DateParam(LESSTHAN, myUpper);
+ DateRangeParam dateRangeParam = new DateRangeParam(lowerBound, upperBound);
+
+ assertFalse(dateRangeParam.isDateWithinRange(myBefore));
+ assertFalse(dateRangeParam.isDateWithinRange(myLower));
+ assertTrue(dateRangeParam.isDateWithinRange(myBetween));
+ assertFalse(dateRangeParam.isDateWithinRange(myUpper));
+ assertFalse(dateRangeParam.isDateWithinRange(myAfter));
+ }
+
+ @Test
+ public void testIsDateWithinRangeInclusive() {
+ DateParam lowerBound = new DateParam(EQUAL, myLower);
+ DateParam upperBound = new DateParam(EQUAL, myUpper);
+ DateRangeParam dateRangeParam = new DateRangeParam(lowerBound, upperBound);
+
+ assertFalse(dateRangeParam.isDateWithinRange(myBefore));
+ assertTrue(dateRangeParam.isDateWithinRange(myLower));
+ assertTrue(dateRangeParam.isDateWithinRange(myBetween));
+ assertTrue(dateRangeParam.isDateWithinRange(myUpper));
+ assertFalse(dateRangeParam.isDateWithinRange(myAfter));
+ }
+
+ @Test
+ public void testIsDateWithinRangeOnlyLower() {
+ DateParam lowerBound = new DateParam(EQUAL, myLower);
+ DateRangeParam dateRangeParam = new DateRangeParam();
+ dateRangeParam.setLowerBound(lowerBound);
+
+ assertFalse(dateRangeParam.isDateWithinRange(myBefore));
+ assertTrue(dateRangeParam.isDateWithinRange(myLower));
+ assertFalse(dateRangeParam.isDateWithinRange(myBetween));
+ assertFalse(dateRangeParam.isDateWithinRange(myUpper));
+ assertFalse(dateRangeParam.isDateWithinRange(myAfter));
+ }
+
+ @Test
+ public void testIsDateWithinRangeOnlyUpper() {
+ DateParam upperBound = new DateParam(EQUAL, myUpper);
+ DateRangeParam dateRangeParam = new DateRangeParam();
+ dateRangeParam.setUpperBound(upperBound);
+
+ assertFalse(dateRangeParam.isDateWithinRange(myBefore));
+ assertFalse(dateRangeParam.isDateWithinRange(myLower));
+ assertFalse(dateRangeParam.isDateWithinRange(myBetween));
+ assertTrue(dateRangeParam.isDateWithinRange(myUpper));
+ assertFalse(dateRangeParam.isDateWithinRange(myAfter));
+ }
+
+ @Test
+ public void testIsDateWithinLowerBoundGreaterThan() {
+ DateParam lowerBound = new DateParam(GREATERTHAN, myLower);
+ DateRangeParam dateRangeParam = new DateRangeParam();
+ dateRangeParam.setLowerBound(lowerBound);
+
+ assertFalse(dateRangeParam.isDateWithinLowerBound(myBefore));
+ assertFalse(dateRangeParam.isDateWithinLowerBound(myLower));
+ assertTrue(dateRangeParam.isDateWithinLowerBound(myBetween));
+ assertTrue(dateRangeParam.isDateWithinLowerBound(myUpper));
+ assertTrue(dateRangeParam.isDateWithinLowerBound(myAfter));
+ }
+
+ @Test
+ public void testIsDateWithinLowerBoundStartsAfter() {
+ DateParam lowerBound = new DateParam(STARTS_AFTER, myLower);
+ DateRangeParam dateRangeParam = new DateRangeParam();
+ dateRangeParam.setLowerBound(lowerBound);
+
+ assertFalse(dateRangeParam.isDateWithinLowerBound(myBefore));
+ assertFalse(dateRangeParam.isDateWithinLowerBound(myLower));
+ assertTrue(dateRangeParam.isDateWithinLowerBound(myBetween));
+ assertTrue(dateRangeParam.isDateWithinLowerBound(myUpper));
+ assertTrue(dateRangeParam.isDateWithinLowerBound(myAfter));
+ }
+
+ @Test
+ public void testIsDateWithinLowerBoundEqual() {
+ DateParam lowerBound = new DateParam(EQUAL, myLower);
+ DateRangeParam dateRangeParam = new DateRangeParam();
+ dateRangeParam.setLowerBound(lowerBound);
+
+ assertFalse(dateRangeParam.isDateWithinLowerBound(myBefore));
+ assertTrue(dateRangeParam.isDateWithinLowerBound(myLower));
+ assertFalse(dateRangeParam.isDateWithinLowerBound(myBetween));
+ assertFalse(dateRangeParam.isDateWithinLowerBound(myUpper));
+ assertFalse(dateRangeParam.isDateWithinLowerBound(myAfter));
+ }
+
+ @Test
+ public void testIsDateWithinLowerBoundGreaterThanOrEquals() {
+ DateParam lowerBound = new DateParam(GREATERTHAN_OR_EQUALS, myLower);
+ DateRangeParam dateRangeParam = new DateRangeParam();
+ dateRangeParam.setLowerBound(lowerBound);
+
+ assertFalse(dateRangeParam.isDateWithinLowerBound(myBefore));
+ assertTrue(dateRangeParam.isDateWithinLowerBound(myLower));
+ assertTrue(dateRangeParam.isDateWithinLowerBound(myBetween));
+ assertTrue(dateRangeParam.isDateWithinLowerBound(myUpper));
+ assertTrue(dateRangeParam.isDateWithinLowerBound(myAfter));
+ }
+
+ @Test
+ public void testIsDateWithinUpperBoundLessThan() {
+ DateParam upperBound = new DateParam(LESSTHAN, myUpper);
+ DateRangeParam dateRangeParam = new DateRangeParam();
+ dateRangeParam.setUpperBound(upperBound);
+
+ assertTrue(dateRangeParam.isDateWithinUpperBound(myBefore));
+ assertTrue(dateRangeParam.isDateWithinUpperBound(myLower));
+ assertTrue(dateRangeParam.isDateWithinUpperBound(myBetween));
+ assertFalse(dateRangeParam.isDateWithinUpperBound(myUpper));
+ assertFalse(dateRangeParam.isDateWithinUpperBound(myAfter));
+ }
+
+ @Test
+ public void testIsDateWithinUpperBoundEndsBefore() {
+ DateParam upperBound = new DateParam(ENDS_BEFORE, myUpper);
+ DateRangeParam dateRangeParam = new DateRangeParam();
+ dateRangeParam.setUpperBound(upperBound);
+
+ assertTrue(dateRangeParam.isDateWithinUpperBound(myBefore));
+ assertTrue(dateRangeParam.isDateWithinUpperBound(myLower));
+ assertTrue(dateRangeParam.isDateWithinUpperBound(myBetween));
+ assertFalse(dateRangeParam.isDateWithinUpperBound(myUpper));
+ assertFalse(dateRangeParam.isDateWithinUpperBound(myAfter));
+ }
+
+ @Test
+ public void testIsDateWithinUpperBoundEqual() {
+ DateParam upperBound = new DateParam(EQUAL, myUpper);
+ DateRangeParam dateRangeParam = new DateRangeParam();
+ dateRangeParam.setUpperBound(upperBound);
+
+ assertFalse(dateRangeParam.isDateWithinUpperBound(myBefore));
+ assertFalse(dateRangeParam.isDateWithinUpperBound(myLower));
+ assertFalse(dateRangeParam.isDateWithinUpperBound(myBetween));
+ assertTrue(dateRangeParam.isDateWithinUpperBound(myUpper));
+ assertFalse(dateRangeParam.isDateWithinUpperBound(myAfter));
+ }
+
+ @Test
+ public void testIsDateWithinUpperBoundLessThanOrEquals() {
+ DateParam upperBound = new DateParam(LESSTHAN_OR_EQUALS, myUpper);
+ DateRangeParam dateRangeParam = new DateRangeParam();
+ dateRangeParam.setUpperBound(upperBound);
+
+ assertTrue(dateRangeParam.isDateWithinUpperBound(myBefore));
+ assertTrue(dateRangeParam.isDateWithinUpperBound(myLower));
+ assertTrue(dateRangeParam.isDateWithinUpperBound(myBetween));
+ assertTrue(dateRangeParam.isDateWithinUpperBound(myUpper));
+ assertFalse(dateRangeParam.isDateWithinUpperBound(myAfter));
+ }
+
/** Can happen e.g. when the query parameter for {@code _lastUpdated} is left empty. */
@Test
public void testParamWithoutPrefixAndWithoutValue() {
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/4_2_0/changes.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/4_2_0/changes.yaml
index e0c2bfd651c..751ab54a333 100644
--- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/4_2_0/changes.yaml
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/4_2_0/changes.yaml
@@ -41,18 +41,27 @@
type: "fix"
title: "A missing mandatory was added to the SNOMED CT CodeSystem that is uploaded when SCT is uploaded to the JPA server. Thanks to Anders Havn for the pull request!"
- item:
- issue: 1643
- type: fix
+ issue: "1643"
+ type: "fix"
title: "When validating resources containing custom valuesets defined in PrePopulatedValidationSupport
outside of the JPA server, sometimes code systems could not be found resulting in false negative
errors."
- item:
- issue: 1588
- type: add
+ issue: "1588"
+ type: "add"
title: "Support for several new operators has been added to the `_filter` support in the JPA server. Thanks
to Anthony Sute for the Pull Request!"
- item:
- issue: 1650
- type: fix
- title: Several misleading comments in documentation code snippets were fixed. Thanks to
- Jafer Khan for the pull request!
+ issue: "1650"
+ type: "fix"
+ title: "Several misleading comments in documentation code snippets were fixed. Thanks to
+ Jafer Khan for the pull request!"
+- item:
+ issue: "1645"
+ type: "add"
+ title: "The following utility methods have been added:
+ DateRangeParam#isDateWithinRange(Date theDate)
DateRangeParam#isDateWithinLowerBound(Date theDate)
DateRangeParam#isDateWithinUpperBound(Date theDate)