Merge pull request #1653 from jamesagnew/1652-daterangeparam-isdatewithinrange-date-thedate--needs-to-account-for-intervals-

Resolve "DateRangeParam.isDateWithinRange(Date theDate) needs to account for intervals."
This commit is contained in:
Diederik Muylwyk 2019-12-31 09:43:32 -05:00 committed by GitHub
commit 20bb939440
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 1 additions and 290 deletions

View File

@ -388,104 +388,6 @@ public class DateRangeParam implements IQueryParameterAnd<DateParam> {
return Objects.hash(myLowerBound, myUpperBound); return Objects.hash(myLowerBound, myUpperBound);
} }
public boolean isDateWithinRange(Date theDate) {
boolean retVal = false;
if (theDate == null) {
throw new NullPointerException("theDate can not be null");
}
boolean hasLowerBound = hasBound(myLowerBound);
boolean hasUpperBound = hasBound(myUpperBound);
boolean hasLowerAndUpperBounds = hasLowerBound && hasUpperBound && (myLowerBound.getValue().getTime() != myUpperBound.getValue().getTime());
if (hasLowerAndUpperBounds) {
retVal = isDateWithinLowerAndUpperBounds(theDate);
} else if (hasLowerBound) {
retVal = isDateWithinLowerBound(theDate);
} else if (hasUpperBound) {
retVal = isDateWithinUpperBound(theDate);
}
return retVal;
}
private boolean isDateWithinLowerAndUpperBounds(Date theDate) {
return isDateWithinLowerBound(theDate, true) && isDateWithinUpperBound(theDate, true);
}
public boolean isDateWithinLowerBound(Date theDate) {
return isDateWithinLowerBound(theDate, false);
}
private boolean isDateWithinLowerBound(Date theDate, boolean theIsRange) {
boolean retVal = false;
if (theDate == null) {
throw new NullPointerException("theDate can not be null");
}
if (hasBound(myLowerBound)) {
long lowerBound = myLowerBound.getValue().getTime();
switch (myLowerBound.getPrefix()) {
case GREATERTHAN:
case STARTS_AFTER:
retVal = theDate.getTime() > lowerBound;
break;
case EQUAL:
if (theIsRange) {
retVal = theDate.getTime() >= lowerBound;
} else {
retVal = theDate.getTime() == lowerBound;
}
break;
case GREATERTHAN_OR_EQUALS:
retVal = theDate.getTime() >= lowerBound;
break;
default:
throw new IllegalStateException("Invalid lower bound comparator: " + myLowerBound.getPrefix());
}
}
return retVal;
}
public boolean isDateWithinUpperBound(Date theDate) {
return isDateWithinUpperBound(theDate, false);
}
private boolean isDateWithinUpperBound(Date theDate, boolean theIsRange) {
boolean retVal = false;
if (theDate == null) {
throw new NullPointerException("theDate can not be null");
}
if (hasBound(myUpperBound)) {
long upperBound = myUpperBound.getValue().getTime();
switch (myUpperBound.getPrefix()) {
case LESSTHAN:
case ENDS_BEFORE:
retVal = theDate.getTime() < upperBound;
break;
case EQUAL:
if (theIsRange) {
retVal = theDate.getTime() <= upperBound;
} else {
retVal = theDate.getTime() == upperBound;
}
break;
case LESSTHAN_OR_EQUALS:
retVal = theDate.getTime() <= upperBound;
break;
default:
throw new IllegalStateException("Invalid upper bound comparator: " + myUpperBound.getPrefix());
}
}
return retVal;
}
public boolean isEmpty() { public boolean isEmpty() {
return (getLowerBoundAsInstant() == null) && (getUpperBoundAsInstant() == null); return (getLowerBoundAsInstant() == null) && (getUpperBoundAsInstant() == null);
} }
@ -583,7 +485,7 @@ public class DateRangeParam implements IQueryParameterAnd<DateParam> {
continue; continue;
} }
if (paramList.size() > 1) { if (paramList.size() > 1) {
throw new InvalidRequestException("DateRange parameter does not suppport OR queries"); throw new InvalidRequestException("DateRange parameter does not support OR queries");
} }
String param = paramList.get(0); String param = paramList.get(0);

View File

@ -3,207 +3,25 @@ package ca.uhn.fhir.rest.param;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.api.QualifiedParamList; import ca.uhn.fhir.rest.api.QualifiedParamList;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.JUnit4; import org.junit.runners.JUnit4;
import org.mockito.Mockito; import org.mockito.Mockito;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
import static ca.uhn.fhir.rest.param.ParamPrefixEnum.*;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@RunWith(JUnit4.class) @RunWith(JUnit4.class)
public class DateRangeParamTest { public class DateRangeParamTest {
private FhirContext fhirContext; 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 @Before
public void initMockContext() { public void initMockContext() {
fhirContext = Mockito.mock(FhirContext.class); 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. */ /** Can happen e.g. when the query parameter for {@code _lastUpdated} is left empty. */
@Test @Test
public void testParamWithoutPrefixAndWithoutValue() { public void testParamWithoutPrefixAndWithoutValue() {

View File

@ -56,12 +56,3 @@
type: "fix" type: "fix"
title: "Several misleading comments in documentation code snippets were fixed. Thanks to title: "Several misleading comments in documentation code snippets were fixed. Thanks to
Jafer Khan for the pull request!" Jafer Khan for the pull request!"
- item:
issue: "1645"
type: "add"
title: "The following utility methods have been added:
<ul>
<li><code>DateRangeParam#isDateWithinRange(Date theDate)</code></li>
<li><code>DateRangeParam#isDateWithinLowerBound(Date theDate)</code></li>
<li><code>DateRangeParam#isDateWithinUpperBound(Date theDate)</code></li>
</ul>"