Skip to content

Commit

Permalink
MAT-7570: Limit the date shift year result range to [1,9999].
Browse files Browse the repository at this point in the history
    The FHIR models use the older java.util.Date class to back the FHIR Date and DateTime values. Java Date does not support a year 0 (as it does not exist in the Gregorian calendar), hence the QICore Date Shift range min must be 1.
  • Loading branch information
jkotanchik-SB committed Aug 30, 2024
1 parent 74c597c commit a4bf377
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.hl7.fhir.r4.model.Base;
import org.hl7.fhir.r4.model.BaseDateTimeType;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Property;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;

@Slf4j
Expand All @@ -25,18 +29,18 @@ public class TestCaseDateShifterService {

private FhirContext fhirContext;

public TestCase shiftDates(TestCase testCase, int shifted) {
public TestCase shiftDates(TestCase testCase, int shiftBy) {
if (testCase == null) {
return null;
}
List<TestCase> shiftedTestCases = shiftDates(List.of(testCase), shifted);
List<TestCase> shiftedTestCases = shiftDates(List.of(testCase), shiftBy);
if (CollectionUtils.isNotEmpty(shiftedTestCases) && shiftedTestCases.size() == 1) {
return shiftedTestCases.get(0);
}
return null;
}

public List<TestCase> shiftDates(List<TestCase> testCases, int shifted) {
public List<TestCase> shiftDates(List<TestCase> testCases, int shiftBy) {
if (CollectionUtils.isEmpty(testCases)) {
return Collections.emptyList();
}
Expand All @@ -51,7 +55,7 @@ public List<TestCase> shiftDates(List<TestCase> testCases, int shifted) {
// convert test case json to bundle
Bundle bundle = parser.parseResource(Bundle.class, testCase.getJson());
// update the test case dates
bundle.getEntry().forEach(entry -> shiftDates(entry.getResource(), shifted));
bundle.getEntry().forEach(entry -> shiftDates(entry.getResource(), shiftBy));
// convert the updated bundle to string and assign back to test case.
String json = parser.encodeResourceToString(bundle);
testCase.setJson(json);
Expand All @@ -63,7 +67,7 @@ public List<TestCase> shiftDates(List<TestCase> testCases, int shifted) {
return shiftedTestCases;
}

void shiftDates(Base baseResource, int shifted) {
void shiftDates(Base baseResource, int shiftBy) {
List<Field> fields = new LinkedList<>();
getAllFields(fields, baseResource.getClass());
for (Field field : fields) {
Expand All @@ -77,11 +81,19 @@ void shiftDates(Base baseResource, int shifted) {
// HAPI will build partial objects when given partial data, like only an extension.
// Verify the target date value is non-null.
if (dateType.getValue() != null) {
dateType.add(1, shifted);
Instant date = dateType.getValue().toInstant();
ZonedDateTime shifted = date.atZone(ZoneId.of("UTC")).plusYears(shiftBy);
if (shifted.getYear() > 9999) {
dateType.setValue(DateUtils.setYears(dateType.getValue(), 9999));
} else if (shifted.getYear() < 0) {
dateType.setValue(DateUtils.setYears(dateType.getValue(), 1));
} else {
dateType.add(1, shiftBy);
}
}
}
} else {
shiftDates(value, shifted);
shiftDates(value, shiftBy);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,4 +262,22 @@ void verifiesPartialDateTypeHasDateValue() {
testCaseDateShifterService.shiftDates(procedure, 1);
assertTrue(copy.getPerformed().equalsDeep(procedure.getPerformed()));
}

@Test
void limitsUpperYearRangeTo9999() {
Patient patient = (Patient) ResourceUtils.getResource(testCaseBundle, "Patient");
Date originalBirthDate = (Date) patient.getBirthDate().clone();
int shiftBy = 1000000; // years
testCaseDateShifterService.shiftDates(patient, shiftBy);
assertEquals(DateUtils.setYears(originalBirthDate, 9999), patient.getBirthDate());
}

@Test
void limitsLowerYearRangeTo0() {
Patient patient = (Patient) ResourceUtils.getResource(testCaseBundle, "Patient");
Date originalBirthDate = (Date) patient.getBirthDate().clone();
int shiftBy = -1000000; // years
testCaseDateShifterService.shiftDates(patient, shiftBy);
assertEquals(DateUtils.setYears(originalBirthDate, 1), patient.getBirthDate());
}
}

0 comments on commit a4bf377

Please sign in to comment.