From 88db5ae884e702287dc51e76ce61064ee6ad1ec5 Mon Sep 17 00:00:00 2001 From: Paul Bastide Date: Thu, 27 Jan 2022 09:04:37 -0500 Subject: [PATCH] MemberMatch improperly generates date formats which are spec invalid #3252 Signed-off-by: Paul Bastide --- .../strategy/DefaultMemberMatchStrategy.java | 18 ++- .../hrex/test/MemberMatchIssuesTest.java | 40 ++++++ .../test/resources/JSON/member-match-in.json | 121 ++++++++++++++++++ 3 files changed, 173 insertions(+), 6 deletions(-) create mode 100644 operation/fhir-operation-member-match/src/test/java/com/ibm/fhir/operation/davinci/hrex/test/MemberMatchIssuesTest.java create mode 100644 operation/fhir-operation-member-match/src/test/resources/JSON/member-match-in.json diff --git a/operation/fhir-operation-member-match/src/main/java/com/ibm/fhir/operation/davinci/hrex/provider/strategy/DefaultMemberMatchStrategy.java b/operation/fhir-operation-member-match/src/main/java/com/ibm/fhir/operation/davinci/hrex/provider/strategy/DefaultMemberMatchStrategy.java index b1cd28b65de..ac6239b2568 100644 --- a/operation/fhir-operation-member-match/src/main/java/com/ibm/fhir/operation/davinci/hrex/provider/strategy/DefaultMemberMatchStrategy.java +++ b/operation/fhir-operation-member-match/src/main/java/com/ibm/fhir/operation/davinci/hrex/provider/strategy/DefaultMemberMatchStrategy.java @@ -1,18 +1,19 @@ /* - * (C) Copyright IBM Corp. 2021 + * (C) Copyright IBM Corp. 2021, 2022 * * SPDX-License-Identifier: Apache-2.0 */ package com.ibm.fhir.operation.davinci.hrex.provider.strategy; -import java.time.temporal.ChronoField; +import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAccessor; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; @@ -148,7 +149,9 @@ public MemberMatchResult executeMemberMatch() throws FHIROperationException { // defined by the customer, it's all in the Compiler. String type = "Patient"; String requestUri = FHIRRequestContext.get().getOriginalRequestUri(); - LOG.fine("SPs for Patient " + patientCompiler.getSearchParameters()); + if (LOG.isLoggable(Level.FINE)) { + LOG.fine("SPs for Patient " + patientCompiler.getSearchParameters()); + } Bundle patientBundle = resourceHelper() .doSearch(type, null, null, patientCompiler.getSearchParameters(), requestUri, null); int size = patientBundle.getEntry().size(); @@ -172,7 +175,9 @@ public MemberMatchResult executeMemberMatch() throws FHIROperationException { coverageToMatch.accept(coverageCompiler); // essentially a search on beneficiary - LOG.info("SPs for Coverage " + coverageCompiler.getSearchParameters()); + if (LOG.isLoggable(Level.FINE)) { + LOG.fine("SPs for Coverage " + coverageCompiler.getSearchParameters()); + } Bundle coverageBundle = resourceHelper().doSearch(type, null, null, coverageCompiler.getSearchParameters(), requestUri, null); if (coverageBundle.getEntry().isEmpty()) { @@ -320,6 +325,8 @@ public static class MemberMatchPatientSearchCompiler extends DefaultVisitor { private Set addressPostalCode = new HashSet<>(); private Set addressCountry = new HashSet<>(); + private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + /** * public constructor which automatically enables child element processing. */ @@ -456,8 +463,7 @@ public boolean visit(String elementName, int elementIndex, Date date) { // SearchParameter: birthdate if ("birthDate".equals(elementName) && date.getValue() != null) { TemporalAccessor acc = date.getValue(); - String searchVal = "eq" + acc.get(ChronoField.YEAR) + "-" + acc.get(ChronoField.MONTH_OF_YEAR) + "-" + acc.get(ChronoField.DAY_OF_MONTH); - searchParams.add("birthdate", searchVal); + searchParams.add("birthdate", "eq" + formatter.format(acc)); } return false; } diff --git a/operation/fhir-operation-member-match/src/test/java/com/ibm/fhir/operation/davinci/hrex/test/MemberMatchIssuesTest.java b/operation/fhir-operation-member-match/src/test/java/com/ibm/fhir/operation/davinci/hrex/test/MemberMatchIssuesTest.java new file mode 100644 index 00000000000..35621af75bf --- /dev/null +++ b/operation/fhir-operation-member-match/src/test/java/com/ibm/fhir/operation/davinci/hrex/test/MemberMatchIssuesTest.java @@ -0,0 +1,40 @@ +/* + * (C) Copyright IBM Corp. 2022 + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.ibm.fhir.operation.davinci.hrex.test; + +import static org.testng.Assert.assertTrue; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import com.ibm.fhir.config.FHIRConfiguration; +import com.ibm.fhir.model.resource.Parameters; +import com.ibm.fhir.model.resource.Patient; +import com.ibm.fhir.model.test.TestUtil; +import com.ibm.fhir.operation.davinci.hrex.provider.strategy.DefaultMemberMatchStrategy.MemberMatchPatientSearchCompiler; + +/** + * A set of tests used in debugging issues + */ +public class MemberMatchIssuesTest { + @BeforeClass + public void setup() { + FHIRConfiguration.setConfigHome("src/test/resources"); + } + + /* + * Addresses issues: MemberMatch improperly generates date formats which are spec invalid #3252 + */ + @Test + public void testCompilerForInteroperabilityUseCase() throws Exception { + Parameters parameters = TestUtil.readLocalResource("JSON/member-match-in.json"); + Patient patient = parameters.getParameter().get(0).getResource().as(Patient.class); + MemberMatchPatientSearchCompiler compiler = new MemberMatchPatientSearchCompiler(); + patient.accept(compiler); + assertTrue(compiler.getSearchParameters().get("birthdate").contains("eq1970-02-02")); + } +} diff --git a/operation/fhir-operation-member-match/src/test/resources/JSON/member-match-in.json b/operation/fhir-operation-member-match/src/test/resources/JSON/member-match-in.json new file mode 100644 index 00000000000..3eab1a86120 --- /dev/null +++ b/operation/fhir-operation-member-match/src/test/resources/JSON/member-match-in.json @@ -0,0 +1,121 @@ +{ + "resourceType": "Parameters", + "id": "member-match-in", + "parameter": [ + { + "name": "MemberPatient", + "resource": { + "resourceType": "Patient", + "id": "MASPatient", + "identifier": [ + { + "system": "https://github.com/synthetichealth/synthea", + "value": "12346" + } + ], + "name": [ + { + "use": "official", + "family": "Meyer", + "given": [ + "Kelly" + ] + } + ], + "gender": "female", + "birthDate": "1970-02-02" + } + }, + { + "name": "CoverageToMatch", + "resource": { + "resourceType": "Coverage", + "id": "9876B1", + "contained": [ + { + "resourceType": "Organization", + "id": "payer", + "identifier": [ + { + "system": "http://hl7.org/fhir/sid/us-npi", + "value": "9876543210" + } + ], + "active": true, + "name": "Old Health Plan", + "endpoint": [ + { + "reference": "http://example.org/old-payer/fhir" + } + ] + } + ], + "identifier": [ + { + "system": "http://example.org/old-payer", + "value": "DH10001235" + } + ], + "status": "draft", + "beneficiary": { + "reference": "Patient/1" + }, + "period": { + "start": "2011-05-23", + "end": "2012-05-23" + }, + "payor": [ + { + "reference": "#payer" + } + ], + "class": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/coverage-class", + "code": "group" + } + ] + }, + "value": "CB135" + }, + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/coverage-class", + "code": "plan" + } + ] + }, + "value": "B37FC" + }, + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/coverage-class", + "code": "subplan" + } + ] + }, + "value": "P7" + }, + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/coverage-class", + "code": "class" + } + ] + }, + "value": "SILVER" + } + ] + } + } + ] +} \ No newline at end of file