TreatmentResponseMatcher { @NotNull public static MatchResult<BiopsyTreatmentResponseData> matchTreatmentResponsesToTreatments(@NotNull String patientIdentifier, @NotNull List<BiopsyTreatmentData> treatments, @NotNull List<BiopsyTreatmentResponseData> responses) { List<BiopsyTreatmentResponseData> matchedResponses = Lists.newArrayList(); List<ValidationFinding> findings = Lists.newArrayList(); Collections.sort(responses); List<BiopsyTreatmentData> sortedTreatments = sortAndWithStartDate(treatments); if (hasOverlappingTreatments(sortedTreatments)) { if (!responses.isEmpty()) { findings.add(responseMatchFinding(patientIdentifier, "Treatments are overlapping. Cannot match any response.", "treatments: " + sortedTreatments)); } return new MatchResult<>(responses, findings); } Iterator<BiopsyTreatmentData> treatmentIterator = sortedTreatments.iterator(); BiopsyTreatmentData currentTreatment = treatmentIterator.hasNext() ? treatmentIterator.next() : null; LocalDate firstTreatmentStart = currentTreatment != null ? currentTreatment.startDate() : null; BiopsyTreatmentData nextTreatment = treatmentIterator.hasNext() ? treatmentIterator.next() : null; boolean hasNewBaselineResponseFound = false; for (BiopsyTreatmentResponseData response : responses) { LocalDate responseDate = response.date(); if (responseMatchable(responseDate, firstTreatmentStart)) { LocalDate nextTreatmentStart = nextTreatment != null ? nextTreatment.startDate() : null; while (nextTreatmentStart != null && responseDate.isAfter(nextTreatmentStart)) { currentTreatment = nextTreatment; nextTreatment = treatmentIterator.hasNext() ? treatmentIterator.next() : null; nextTreatmentStart = nextTreatment != null ? nextTreatment.startDate() : null; hasNewBaselineResponseFound = false; } if (hasNewBaselineResponseFound) { matchedResponses.add(response); findings.add(responseMatchFinding(patientIdentifier, "Response after new baseline and before next treatment", "response: " + response)); } else { String actualResponse = response.response(); if (actualResponse != null && actualResponse.equalsIgnoreCase("ne")) { matchedResponses.add(response); hasNewBaselineResponseFound = true; } else { matchedResponses.add(ImmutableBiopsyTreatmentResponseData.builder() .from(response) .treatmentId(currentTreatment.id()) .build()); } } } else { matchedResponses.add(response); } } return new MatchResult<>(matchedResponses, findings); } private  TreatmentResponseMatcher(); @NotNull static MatchResult<BiopsyTreatmentResponseData> matchTreatmentResponsesToTreatments(@NotNull String patientIdentifier,
            @NotNull List<BiopsyTreatmentData> treatments, @NotNull List<BiopsyTreatmentResponseData> responses);  }
@Test public void responseBeforeStartFails() { List<BiopsyTreatmentData> treatments = Lists.newArrayList(TREATMENT_FEB2015_JUL2015); List<BiopsyTreatmentResponseData> responses = Lists.newArrayList(RESPONSE_JAN2015); List<BiopsyTreatmentResponseData> matchedResponses = TreatmentResponseMatcher.matchTreatmentResponsesToTreatments("patient", treatments, responses).values(); assertEquals(matchedResponses.size(), responses.size()); assertNull(matchedResponses.get(0).treatmentId()); }
@Test public void responseSameDateAsStartFails() { List<BiopsyTreatmentData> treatments = Lists.newArrayList(TREATMENT_FEB2015_JUL2015); List<BiopsyTreatmentResponseData> responses = Lists.newArrayList(RESPONSE_FEB2015); List<BiopsyTreatmentResponseData> matchedResponses = TreatmentResponseMatcher.matchTreatmentResponsesToTreatments("patient", treatments, responses).values(); assertEquals(matchedResponses.size(), responses.size()); assertNull(matchedResponses.get(0).treatmentId()); }
@Test public void responseAfterStartBeforeEndSucceeds() { List<BiopsyTreatmentData> treatments = Lists.newArrayList(TREATMENT_FEB2015_JUL2015); List<BiopsyTreatmentResponseData> responses = Lists.newArrayList(RESPONSE_MAR2015); List<BiopsyTreatmentResponseData> matchedResponses = TreatmentResponseMatcher.matchTreatmentResponsesToTreatments("patient", treatments, responses).values(); assertEquals(matchedResponses.size(), responses.size()); assertMatch(treatments.get(0).id(), matchedResponses.get(0).treatmentId()); }
@Test public void responseAfterStartSameDateAsEndSucceeds() { List<BiopsyTreatmentData> treatments = Lists.newArrayList(TREATMENT_FEB2015_JUL2015); List<BiopsyTreatmentResponseData> responses = Lists.newArrayList(RESPONSE_JUL2015); List<BiopsyTreatmentResponseData> matchedResponses = TreatmentResponseMatcher.matchTreatmentResponsesToTreatments("patient", treatments, responses).values(); assertEquals(matchedResponses.size(), responses.size()); assertMatch(treatments.get(0).id(), matchedResponses.get(0).treatmentId()); }
@Test public void responseAfterEndSucceeds() { List<BiopsyTreatmentData> treatments = Lists.newArrayList(TREATMENT_FEB2015_JUL2015); List<BiopsyTreatmentResponseData> responses = Lists.newArrayList(RESPONSE_AUG2015); List<BiopsyTreatmentResponseData> matchedResponses = TreatmentResponseMatcher.matchTreatmentResponsesToTreatments("patient", treatments, responses).values(); assertEquals(matchedResponses.size(), responses.size()); assertMatch(treatments.get(0).id(), matchedResponses.get(0).treatmentId()); }
@Test public void responseAfterStartBeforeNullSucceeds() { List<BiopsyTreatmentData> treatments = Lists.newArrayList(TREATMENT_FEB2015_NULL); List<BiopsyTreatmentResponseData> responses = Lists.newArrayList(RESPONSE_MAR2015); List<BiopsyTreatmentResponseData> matchedResponses = TreatmentResponseMatcher.matchTreatmentResponsesToTreatments("patient", treatments, responses).values(); assertEquals(matchedResponses.size(), responses.size()); assertMatch(treatments.get(0).id(), matchedResponses.get(0).treatmentId()); }
@Test public void responseNullFails() { List<BiopsyTreatmentData> treatments = Lists.newArrayList(TREATMENT_FEB2015_NULL); List<BiopsyTreatmentResponseData> responses = Lists.newArrayList(RESPONSE_NULL); List<BiopsyTreatmentResponseData> matchedResponses = TreatmentResponseMatcher.matchTreatmentResponsesToTreatments("patient", treatments, responses).values(); assertEquals(matchedResponses.size(), responses.size()); assertNull(matchedResponses.get(0).treatmentId()); }
@Test public void multipleResponsesMatchTreatment() { List<BiopsyTreatmentData> treatments = Lists.newArrayList(TREATMENT_FEB2015_NULL); List<BiopsyTreatmentResponseData> responses = Lists.newArrayList(RESPONSE_MAR2015, RESPONSE_JUL2015); List<BiopsyTreatmentResponseData> matchedResponses = TreatmentResponseMatcher.matchTreatmentResponsesToTreatments("patient", treatments, responses).values(); assertEquals(matchedResponses.size(), responses.size()); assertMatch(treatments.get(0).id(), matchedResponses.get(0).treatmentId()); assertMatch(treatments.get(0).id(), matchedResponses.get(1).treatmentId()); }
@Test public void overlappingTreatmentsCannotBeUsedForMatching() { List<BiopsyTreatmentData> treatments = Lists.newArrayList(TREATMENT_FEB2015_JUL2015, TREATMENT_FEB2015_NULL); List<BiopsyTreatmentResponseData> responses = Lists.newArrayList(RESPONSE_MAR2015); List<BiopsyTreatmentResponseData> matchedResponses = TreatmentResponseMatcher.matchTreatmentResponsesToTreatments("patient", treatments, responses).values(); assertEquals(matchedResponses.size(), responses.size()); assertNull(matchedResponses.get(0).treatmentId()); }
@Test public void realTimelineWorksAsExpected() { List<BiopsyTreatmentData> treatments = Lists.newArrayList(TREATMENT_JAN2015_JUL2015, TREATMENT_OCT2015_NULL); List<BiopsyTreatmentResponseData> responses = Lists.newArrayList(RESPONSE_FEB2015, RESPONSE_MAR2015, RESPONSE_AUG2015_BASELINE, RESPONSE_SEP2015, RESPONSE_NOV2015); List<BiopsyTreatmentResponseData> matchedResponses = TreatmentResponseMatcher.matchTreatmentResponsesToTreatments("patient", treatments, responses).values(); assertEquals(matchedResponses.size(), responses.size()); assertMatch(treatments.get(0).id(), matchedResponses.get(0).treatmentId()); assertMatch(treatments.get(0).id(), matchedResponses.get(1).treatmentId()); assertNull(matchedResponses.get(2).treatmentId()); assertNull(matchedResponses.get(3).treatmentId()); assertMatch(treatments.get(1).id(), matchedResponses.get(4).treatmentId()); }