diff --git a/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/.index.json b/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/.index.json index aec33ec7de0..00084f3d89a 100644 --- a/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/.index.json +++ b/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/.index.json @@ -51,30 +51,6 @@ "url": "http://hl7.org/fhir/us/carin-bb/ImplementationGuide/hl7.fhir.us.carin-bb", "version": "0.1.0" }, - { - "filename": "SearchParameter-carin-bb-searchparameter-coverage-patient.json", - "resourceType": "SearchParameter", - "id": "carin-bb-searchparameter-coverage-patient", - "url": "http://hl7.org/fhir/us/carin/SearchParameter/carin-bb-searchparameter-coverage-patient", - "version": "0.1.0", - "type": "reference" - }, - { - "filename": "SearchParameter-carin-bb-searchparameter-explanationofbenefit-created.json", - "resourceType": "SearchParameter", - "id": "carin-bb-searchparameter-explanationofbenefit-created", - "url": "http://hl7.org/fhir/us/carin/SearchParameter/carin-bb-searchparameter-explanationofbenefit-created", - "version": "0.1.0", - "type": "date" - }, - { - "filename": "SearchParameter-carin-bb-searchparameter-explanationofbenefit-patient.json", - "resourceType": "SearchParameter", - "id": "carin-bb-searchparameter-explanationofbenefit-patient", - "url": "http://hl7.org/fhir/us/carin/SearchParameter/carin-bb-searchparameter-explanationofbenefit-patient", - "version": "0.1.0", - "type": "reference" - }, { "filename": "StructureDefinition-CARIN-BB-Coverage.json", "resourceType": "StructureDefinition", diff --git a/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/SearchParameter-carin-bb-searchparameter-coverage-patient.json b/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/SearchParameter-carin-bb-searchparameter-coverage-patient.json deleted file mode 100755 index 7de7ef4fe37..00000000000 --- a/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/SearchParameter-carin-bb-searchparameter-coverage-patient.json +++ /dev/null @@ -1 +0,0 @@ -{"resourceType":"SearchParameter","id":"carin-bb-searchparameter-coverage-patient","meta":{"versionId":"1","lastUpdated":"2019-12-16T06:41:13.000+00:00"},"text":{"status":"generated","div":"

SearchParameter: CARINBlueButton_Coverage_Patient_SearchParameter

description : Retrieve coverages for a patient\n

"},"extension":[{"url":"http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status","valueCode":"trial-use"}],"url":"http://hl7.org/fhir/us/carin/SearchParameter/carin-bb-searchparameter-coverage-patient","version":"0.1.0","name":"CARINBlueButton_Coverage_Patient_SearchParameter","derivedFrom":"http://hl7.org/fhir/SearchParameter/Coverage-patient","status":"active","experimental":false,"date":"2019-12-01T09:48:45+00:00","publisher":"HL7 International & CARIN Alliance","contact":[{"telecom":[{"system":"url","value":"https://www.carinalliance.com/about-us/contact-us"}]}],"description":"Retrieve coverages for a patient","jurisdiction":[{"coding":[{"system":"urn:iso:std:iso:3166","code":"US","display":"United States of America"}]}],"code":"patient","base":["Coverage"],"type":"reference","expression":"Coverage.beneficiary","xpath":"f:Coverage/f:beneficiary","xpathUsage":"normal","target":["Patient"]} \ No newline at end of file diff --git a/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/SearchParameter-carin-bb-searchparameter-explanationofbenefit-created.json b/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/SearchParameter-carin-bb-searchparameter-explanationofbenefit-created.json deleted file mode 100755 index 45a5070befe..00000000000 --- a/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/SearchParameter-carin-bb-searchparameter-explanationofbenefit-created.json +++ /dev/null @@ -1 +0,0 @@ -{"resourceType":"SearchParameter","id":"carin-bb-searchparameter-explanationofbenefit-created","meta":{"versionId":"1","lastUpdated":"2019-12-16T06:41:13.000+00:00"},"text":{"status":"generated","div":"

SearchParameter: CARINBlueButton_ExplanationOfBenefit_Created_SearchParameter

description : The creation date for the EOB\n

"},"extension":[{"url":"http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status","valueCode":"trial-use"}],"url":"http://hl7.org/fhir/us/carin/SearchParameter/carin-bb-searchparameter-explanationofbenefit-created","version":"0.1.0","name":"CARINBlueButton_ExplanationOfBenefit_Created_SearchParameter","derivedFrom":"http://hl7.org/fhir/SearchParameter/ExplanationOfBenefit-created","status":"active","experimental":false,"date":"2019-12-01T09:48:45+00:00","publisher":"HL7 International & CARIN Alliance","contact":[{"telecom":[{"system":"url","value":"https://www.carinalliance.com/about-us/contact-us"}]}],"description":"The creation date for the EOB","jurisdiction":[{"coding":[{"system":"urn:iso:std:iso:3166","code":"US","display":"United States of America"}]}],"code":"status","base":["ExplanationOfBenefit"],"type":"date","expression":"explanationofbenefit.created","xpath":"f:explanationofbenefit/f:created","xpathUsage":"normal","comparator":["eq","ne","gt","ge","lt","le","sa","eb","ap"]} \ No newline at end of file diff --git a/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/SearchParameter-carin-bb-searchparameter-explanationofbenefit-patient.json b/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/SearchParameter-carin-bb-searchparameter-explanationofbenefit-patient.json deleted file mode 100755 index 5b222d60d4c..00000000000 --- a/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/SearchParameter-carin-bb-searchparameter-explanationofbenefit-patient.json +++ /dev/null @@ -1 +0,0 @@ -{"resourceType":"SearchParameter","id":"carin-bb-searchparameter-explanationofbenefit-patient","meta":{"versionId":"1","lastUpdated":"2019-12-16T06:41:13.000+00:00"},"text":{"status":"generated","div":"

SearchParameter: CARINBlueButton_ExplanationOfBenefit_Patient_SearchParameter

description : The reference to the patient\n

"},"extension":[{"url":"http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status","valueCode":"trial-use"}],"url":"http://hl7.org/fhir/us/carin/SearchParameter/carin-bb-searchparameter-explanationofbenefit-patient","version":"0.1.0","name":"CARINBlueButton_ExplanationOfBenefit_Patient_SearchParameter","derivedFrom":"http://hl7.org/fhir/SearchParameter/ExplanationOfBenefit-patient","status":"active","experimental":false,"date":"2019-12-01T09:48:45+00:00","publisher":"HL7 International & CARIN Alliance","contact":[{"telecom":[{"system":"url","value":"https://www.carinalliance.com/about-us/contact-us"}]}],"description":"The reference to the patient","jurisdiction":[{"coding":[{"system":"urn:iso:std:iso:3166","code":"US","display":"United States of America"}]}],"code":"patient","base":["ExplanationOfBenefit"],"type":"reference","expression":"explanationofbenefit.patient","xpath":"f:explanationofbenefit/f:patient","xpathUsage":"normal","target":["Patient"]} \ No newline at end of file diff --git a/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/spec.internals b/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/spec.internals index 0988b5066f9..d7f025b4b62 100755 --- a/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/spec.internals +++ b/fhir-ig-carin-bb/src/main/resources/hl7/fhir/us/carin-bb/package/spec.internals @@ -236,18 +236,6 @@ "PractitionerRole-PractitionerRole1.ttl.html", "PractitionerRole-PractitionerRole1.xml.html", "profiles.html", - "SearchParameter-carin-bb-searchparameter-coverage-patient.html", - "SearchParameter-carin-bb-searchparameter-coverage-patient.json.html", - "SearchParameter-carin-bb-searchparameter-coverage-patient.ttl.html", - "SearchParameter-carin-bb-searchparameter-coverage-patient.xml.html", - "SearchParameter-carin-bb-searchparameter-explanationofbenefit-created.html", - "SearchParameter-carin-bb-searchparameter-explanationofbenefit-created.json.html", - "SearchParameter-carin-bb-searchparameter-explanationofbenefit-created.ttl.html", - "SearchParameter-carin-bb-searchparameter-explanationofbenefit-created.xml.html", - "SearchParameter-carin-bb-searchparameter-explanationofbenefit-patient.html", - "SearchParameter-carin-bb-searchparameter-explanationofbenefit-patient.json.html", - "SearchParameter-carin-bb-searchparameter-explanationofbenefit-patient.ttl.html", - "SearchParameter-carin-bb-searchparameter-explanationofbenefit-patient.xml.html", "searchparams.html", "Search_Parameters.html", "StructureDefinition-CARIN-BB-Coverage-definitions.html", diff --git a/fhir-server-test/src/test/java/com/ibm/fhir/server/test/profiles/CarinBlueButtonTest.java b/fhir-server-test/src/test/java/com/ibm/fhir/server/test/profiles/CarinBlueButtonTest.java index 6150ad6bfaa..a10585c82a4 100644 --- a/fhir-server-test/src/test/java/com/ibm/fhir/server/test/profiles/CarinBlueButtonTest.java +++ b/fhir-server-test/src/test/java/com/ibm/fhir/server/test/profiles/CarinBlueButtonTest.java @@ -6,6 +6,11 @@ package com.ibm.fhir.server.test.profiles; +import static com.ibm.fhir.model.type.String.string; +import static com.ibm.fhir.model.type.Uri.uri; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; + import java.util.Arrays; import java.util.List; @@ -17,7 +22,10 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import com.ibm.fhir.client.FHIRParameters; +import com.ibm.fhir.client.FHIRResponse; import com.ibm.fhir.core.FHIRMediaType; +import com.ibm.fhir.model.resource.Bundle; import com.ibm.fhir.model.resource.CareTeam; import com.ibm.fhir.model.resource.Coverage; import com.ibm.fhir.model.resource.ExplanationOfBenefit; @@ -27,12 +35,29 @@ import com.ibm.fhir.model.resource.Practitioner; import com.ibm.fhir.model.resource.PractitionerRole; import com.ibm.fhir.model.test.TestUtil; +import com.ibm.fhir.model.type.Canonical; +import com.ibm.fhir.model.type.Code; +import com.ibm.fhir.model.type.CodeableConcept; +import com.ibm.fhir.model.type.Coding; +import com.ibm.fhir.model.type.Identifier; +import com.ibm.fhir.model.type.Meta; import com.ibm.fhir.model.type.Reference; /** - * Copy over http://hl7.org/fhir/us/carin-bb/2020Feb/Examples.html + * Tests using http://hl7.org/fhir/us/carin-bb/2020Feb/Examples.html And the given profile. */ public class CarinBlueButtonTest extends ProfilesTestBase { + private String coverageId = null; + private String careTeamId = null; + private String organizationId = null; + private String organizationOrg1Id = null; + private String organizationOrg45Id = null; + private String locationId = null; + private String patientId = null; + private String practitionerRoleId = null; + private String practitionerId = null; + private String explanationOfBenefitId = null; + @Override public List getRequiredProfiles() { //@formatter:off @@ -49,24 +74,59 @@ public List getRequiredProfiles() { //@formatter:on } - private String coverageId = null; - private String careTeamId = null; - private String organizationId = null; - private String organizationOrg1Id = null; - private String organizationOrg45Id = null; - private String locationId = null; - private String patientId = null; - private String practitionerRoleId = null; - private String practitionerId = null; - private String explanationOfBenefitId = null; - // Load Organization Resources public void loadOrganization() throws Exception { String resource = "json/spec/organization-example.json"; WebTarget target = getWebTarget(); Organization organization = TestUtil.readExampleResource(resource); + + // Add profile + extra fields required by profile. + Canonical profile = Canonical.of("http://hl7.org/fhir/us/carin/StructureDefinition/carin-bb-organization"); + Meta meta = organization.getMeta().toBuilder().profile(profile).build(); + + // @formatter:off + CodeableConcept type = + CodeableConcept.builder() + .coding(Coding.builder() + .code(Code.of("NPI")) + .display(string("National provider identifier")) + .system(uri("http://terminology.hl7.org/CodeSystem/v2-0203")) + .build()) + .build(); + + Identifier identifierNPI = + Identifier.builder() + .system(uri("http://hl7.org/fhir/sid/us-npi")) + .value(string("1234556")) + .type(type) + .build(); + + type = CodeableConcept.builder() + .coding(Coding.builder() + .code(Code.of("TAX")) + .display(string("Tax ID number")) + .system(uri("http://terminology.hl7.org/CodeSystem/v2-0203")) + .build()) + .build(); + + Identifier identifierTaxId = + Identifier.builder() + .system(uri("urn:oid:2.16.840.1.113883.4.4")) + .value(string("1234567")) + .type(type) + .build(); + + organization = organization.toBuilder() + .meta(meta) + .identifier(identifierNPI, identifierTaxId) + .active(com.ibm.fhir.model.type.Boolean.TRUE) + .build(); + // @formatter:on + Entity entity = Entity.entity(organization, FHIRMediaType.APPLICATION_FHIR_JSON); Response response = target.path("Organization").request().post(entity, Response.class); + + System.out.println(response.readEntity(String.class)); assertResponse(response, Response.Status.CREATED.getStatusCode()); organizationId = getLocationLogicalId(response); response = target.path("Organization/" + organizationId).request(FHIRMediaType.APPLICATION_FHIR_JSON).get(); @@ -91,11 +151,9 @@ public void loadOrganizationOrg45() throws Exception { Organization organization = TestUtil.readExampleResource(resource); Entity entity = Entity.entity(organization, FHIRMediaType.APPLICATION_FHIR_JSON); Response response = target.path("Organization").request().post(entity, Response.class); - String out = response.readEntity(String.class); - System.out.println(out); assertResponse(response, Response.Status.CREATED.getStatusCode()); organizationOrg45Id = getLocationLogicalId(response); - + response = target.path("Organization/" + organizationOrg45Id).request(FHIRMediaType.APPLICATION_FHIR_JSON).get(); assertResponse(response, Response.Status.OK.getStatusCode()); } @@ -105,6 +163,9 @@ public void loadCoverage() throws Exception { WebTarget target = getWebTarget(); Coverage coverage = TestUtil.readExampleResource("json/profiles/fhir-ig-carin-bb/Coverage-Coverage1.json"); + Reference org45ref = Reference.builder().reference(com.ibm.fhir.model.type.String.of("Organization/" + organizationOrg45Id)).build(); + coverage = coverage.toBuilder().payor(org45ref).build(); + Entity entity = Entity.entity(coverage, FHIRMediaType.APPLICATION_FHIR_JSON); Response response = target.path("Coverage").request().post(entity, Response.class); assertResponse(response, Response.Status.CREATED.getStatusCode()); @@ -121,7 +182,7 @@ public void loadPatient() throws Exception { Patient patient = TestUtil.readExampleResource("json/profiles/fhir-ig-carin-bb/Patient-Patient1.json"); Entity entity = Entity.entity(patient, FHIRMediaType.APPLICATION_FHIR_JSON); - Response response = target.path("Coverage").request().post(entity, Response.class); + Response response = target.path("Patient").request().post(entity, Response.class); assertResponse(response, Response.Status.CREATED.getStatusCode()); patientId = getLocationLogicalId(response); @@ -171,6 +232,7 @@ public void loadInsurerClaim() throws Exception { * "code" : "insurer", "base" : ["Claim"], "type" : "reference", "expression" : "Claim.insurer", "xpath" : * "f:Claim/f:insurer", "xpathUsage" : "normal", "target" : ["Organization"] */ + // insurerClaimId } // Load Location Resources @@ -184,7 +246,6 @@ public void loadLocation() throws Exception { locationId = getLocationLogicalId(response); - // Next, call the 'read' API to retrieve the new Location and verify it. response = target.path("Location/" + locationId).request(FHIRMediaType.APPLICATION_FHIR_JSON).get(); assertResponse(response, Response.Status.OK.getStatusCode()); } @@ -193,14 +254,13 @@ public void loadLocation() throws Exception { public void loadExplanationOfBenefits() throws Exception { WebTarget target = getWebTarget(); - ExplanationOfBenefit eob = TestUtil.readExampleResource("json/profiles/fhir-ig-carin-bb/"); + ExplanationOfBenefit eob = TestUtil.readExampleResource("json/profiles/fhir-ig-carin-bb/ExplanationOfBenefit-EOB1.json"); Entity entity = Entity.entity(eob, FHIRMediaType.APPLICATION_FHIR_JSON); Response response = target.path("ExplanationOfBenefit").request().post(entity, Response.class); assertResponse(response, Response.Status.CREATED.getStatusCode()); explanationOfBenefitId = getLocationLogicalId(response); - // Next, call the 'read' API to retrieve the new Location and verify it. response = target.path("ExplanationOfBenefit/" + explanationOfBenefitId).request(FHIRMediaType.APPLICATION_FHIR_JSON).get(); assertResponse(response, Response.Status.OK.getStatusCode()); } @@ -208,14 +268,17 @@ public void loadExplanationOfBenefits() throws Exception { // Load PractitionerRole Resources public void loadPractitionerRole() throws Exception { Reference location = Reference.builder().reference(com.ibm.fhir.model.type.String.of("Location/" + locationId)).build(); + + Reference practitioner = Reference.builder().reference(com.ibm.fhir.model.type.String.of("Practitioner/" + practitionerId)).build(); + + Reference organization = Reference.builder().reference(com.ibm.fhir.model.type.String.of("Organization/" + organizationOrg45Id)).build(); + PractitionerRole practitionerRole = TestUtil.readExampleResource("json/profiles/fhir-ig-carin-bb/PractitionerRole-PractitionerRole1.json"); - practitionerRole = practitionerRole.toBuilder().location(location).build(); + practitionerRole = practitionerRole.toBuilder().location(location).organization(organization).practitioner(practitioner).build(); WebTarget target = getWebTarget(); Entity entityPractitionerRole = Entity.entity(practitionerRole, FHIRMediaType.APPLICATION_FHIR_JSON); Response response = target.path("PractitionerRole").request().post(entityPractitionerRole, Response.class); - String res = response.readEntity(String.class); - System.out.println(res); assertResponse(response, Response.Status.CREATED.getStatusCode()); practitionerRoleId = getLocationLogicalId(response); @@ -226,110 +289,421 @@ public void loadPractitionerRole() throws Exception { // Load Resources @BeforeClass public void loadResources() throws Exception { - loadLocation(); // Dependent -> loadOrganization, loadPractitionerRole - loadPractitionerRole(); // Dependent -> - loadInsurerClaim(); - loadOrganization(); // Dependent -> testCoverage - loadOrganizationOrg1(); - loadOrganizationOrg45(); - loadCoverage(); + if (!skip) { + loadLocation(); // Dependent -> loadOrganization, loadPractitionerRole + loadOrganization(); // Dependent -> testCoverage + loadOrganizationOrg1(); + loadOrganizationOrg45(); + loadProvider(); + loadPractitionerRole(); // Depends on -> Location + loadCoverage(); // Depends on -> loadOrganizationOrg45 + loadPatient(); + loadCareteam(); + loadInsurerClaim(); + loadExplanationOfBenefits(); + } + } - // METHOD_LOAD_COVERAGE, METHOD_LOAD_PATIENT, METHOD_LOAD_PROVIDER, METHOD_LOAD_CARETEAM, METHOD_LOAD_INSURER, - // METHOD_LOAD_LOCATION - loadExplanationOfBenefits(); + // Delete Resources + public void deleteOrganization() throws Exception { + WebTarget target = getWebTarget(); + Response response = target.path("Organization/" + organizationId).request(FHIRMediaType.APPLICATION_FHIR_JSON).delete(); + assertResponse(response, Response.Status.OK.getStatusCode()); } - @AfterClass - public void deleteResources() { + public void deleteOrganizationOrg1() throws Exception { WebTarget target = getWebTarget(); - // Response response = target.path("Location/" + - // locationId).request(FHIRMediaType.APPLICATION_FHIR_JSON).delete(); - // assertResponse(response, Response.Status.OK.getStatusCode()); - // response = target.path("Location/" + locationAbsId).request(FHIRMediaType.APPLICATION_FHIR_JSON).delete(); - // assertResponse(response, Response.Status.OK.getStatusCode()); + Response response = target.path("Organization/" + organizationId).request(FHIRMediaType.APPLICATION_FHIR_JSON).delete(); + assertResponse(response, Response.Status.OK.getStatusCode()); + } - // Remove Chained Reference - // response = target.path("PractitionerRole/" + - // practitionerRoleId).request(FHIRMediaType.APPLICATION_FHIR_JSON).delete(); + public void deleteOrganizationOrg45() throws Exception { + WebTarget target = getWebTarget(); + Response response = target.path("Organization/" + organizationOrg45Id).request(FHIRMediaType.APPLICATION_FHIR_JSON).delete(); + assertResponse(response, Response.Status.OK.getStatusCode()); } - @Test - public void testCoverage() throws Exception { + // Delete Coverage Resources + public void deleteCoverage() throws Exception { + WebTarget target = getWebTarget(); + Response response = target.path("Coverage/" + coverageId).request(FHIRMediaType.APPLICATION_FHIR_JSON).delete(); + assertResponse(response, Response.Status.OK.getStatusCode()); + } + + // Delete Patient Resources + public void deletePatient() throws Exception { + WebTarget target = getWebTarget(); + Response response = target.path("Patient/" + patientId).request(FHIRMediaType.APPLICATION_FHIR_JSON).delete(); + assertResponse(response, Response.Status.OK.getStatusCode()); + } + + // Delete Provider Resources + public void deleteProvider() throws Exception { + WebTarget target = getWebTarget(); + Response response = target.path("Practitioner/" + practitionerId).request(FHIRMediaType.APPLICATION_FHIR_JSON).delete(); + assertResponse(response, Response.Status.OK.getStatusCode()); + } + + // Delete CareTeam Resources + public void deleteCareteam() throws Exception { + WebTarget target = getWebTarget(); + Response response = target.path("CareTeam/" + careTeamId).request(FHIRMediaType.APPLICATION_FHIR_JSON).delete(); + assertResponse(response, Response.Status.OK.getStatusCode()); + } + + // Delete Insurer Resources + public void deleteInsurerClaim() throws Exception { /* - * The Coverage resources can represent a Payor with a reference to an Organization resource. The server MAY - * support the "_include" parameter for search parameters defined on these elements. The client application - * SHALL support "_include" parameter for search parameters defined on these elements. For example, a server MAY - * be capable of returning and Organization (payor) for a Coverage using: GET - * [base]/Coverage?_id=[id]&_include=Coverage:payor + * "code" : "insurer", "base" : ["Claim"], "type" : "reference", "expression" : "Claim.insurer", "xpath" : + * "f:Claim/f:insurer", "xpathUsage" : "normal", "target" : ["Organization"] */ + // insurerClaimId + } + // Delete Location Resources + public void deleteLocation() throws Exception { + WebTarget target = getWebTarget(); + Response response = target.path("Location/" + locationId).request(FHIRMediaType.APPLICATION_FHIR_JSON).delete(); + assertResponse(response, Response.Status.OK.getStatusCode()); } - // --------------------------------------------------------------------------------------------------------- - // Loads the resources related to CarinBB - public void loadResourcesDefault() throws Exception { + // Delete Explanation of Benefits Resources + public void deleteExplanationOfBenefits() throws Exception { WebTarget target = getWebTarget(); - Location location = TestUtil.readExampleResource("json/spec/location-example.json"); + Response response = target.path("ExplanationOfBenefit/" + explanationOfBenefitId).request(FHIRMediaType.APPLICATION_FHIR_JSON).delete(); + assertResponse(response, Response.Status.OK.getStatusCode()); + } - Entity entity = Entity.entity(location, FHIRMediaType.APPLICATION_FHIR_JSON); - Response response = target.path("Location").request().post(entity, Response.class); - assertResponse(response, Response.Status.CREATED.getStatusCode()); - locationId = getLocationLogicalId(response); + // Delete PractitionerRole Resources + public void deletePractitionerRole() throws Exception { + WebTarget target = getWebTarget(); + Response response = target.path("PractitionerRole/" + practitionerRoleId).request(FHIRMediaType.APPLICATION_FHIR_JSON).delete(); + assertResponse(response, Response.Status.OK.getStatusCode()); + } - // Entity entityAbs = Entity.entity(locationAbs, FHIRMediaType.APPLICATION_FHIR_JSON); - // Response responseAbs = target.path("Location").request().post(entityAbs, Response.class); - // assertResponse(responseAbs, Response.Status.CREATED.getStatusCode()); + @AfterClass + public void deleteResources() throws Exception { + if (!skip) { + deleteLocation(); + deleteOrganization(); + deleteOrganizationOrg1(); + deleteOrganizationOrg45(); + deletePractitionerRole(); + deleteCoverage(); + deletePatient(); + deleteProvider(); + deleteCareteam(); + deleteInsurerClaim(); + deleteExplanationOfBenefits(); + } + } - // locationAbsId = getLocationLogicalId(responseAbs); + @Test + public void testLocationId() throws Exception { + if (!skip) { + // A common call -> GET [base]/Location?_id=[id] + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("_id", locationId); + FHIRResponse response = client.search(Location.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, locationId); + } + } - // Next, call the 'read' API to retrieve the new Location and verify it. - response = target.path("Location/" + locationId).request(FHIRMediaType.APPLICATION_FHIR_JSON).get(); - assertResponse(response, Response.Status.OK.getStatusCode()); + @Test + public void testPractitionerId() throws Exception { + if (!skip) { + // A common call -> GET [base]/Practitioner?_id=[id] + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("_id", practitionerId); + FHIRResponse response = client.search(Practitioner.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, practitionerId); + } } @Test - public void testBlueButton() { + public void testPractitionerRoleIdIncludeOrg() throws Exception { if (!skip) { - System.out.println("VALID"); + // A common call -> GET [base]/PractitionerRole?_id=[id] + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("_id", practitionerRoleId); + parameters.searchParam("_include", "PractitionerRole:organization"); + FHIRResponse response = client.search(PractitionerRole.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, practitionerRoleId, organizationOrg45Id); } } @Test - public void testCarePlanCareTeamSearch() { - /* - * "description" : "Who's involved in plan?", "code" : "care-team", "base" : ["CarePlan"], "type" : "reference", - * "expression" : "CarePlan.careTeam", "xpath" : "f:CarePlan/f:careTeam", "xpathUsage" : "normal", "target" : - * ["CareTeam"] - */ + public void testPractitionerRoleIdIncludePractitioner() throws Exception { + if (!skip) { + // A common call -> GET [base]/PractitionerRole?_id=[id] + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("_id", practitionerRoleId); + parameters.searchParam("_include", "PractitionerRole:practitioner"); + FHIRResponse response = client.search(PractitionerRole.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, practitionerRoleId, practitionerId); + } + } + @Test + public void testPractitionerRoleIdIncludeOrgAndPractitioner() throws Exception { + if (!skip) { + // A common call -> GET [base]/PractitionerRole?_id=[id] + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("_id", practitionerRoleId); + parameters.searchParam("_include", "PractitionerRole:organization"); + // From US Core (2nd indirect profile being tested) + parameters.searchParam("_include", "PractitionerRole:practitioner"); + FHIRResponse response = client.search(PractitionerRole.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, practitionerRoleId, organizationOrg45Id, practitionerId); + } } @Test - public void testCARINBlueButton_Coverage_Patient_SearchParameter() { - // Name: CARINBlueButton_Coverage_Patient_SearchParameter - /* - * "code": "patient", "base": ["Coverage"], "type": "reference", "expression": "Coverage.beneficiary", "xpath": - * "f:Coverage/f:beneficiary", CARINBlueButton_Coverage_Patient_SearchParameter - */ + public void testPatientId() throws Exception { + if (!skip) { + // A common call -> GET [base]/Patient?_id=[id] + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("_id", patientId); + FHIRResponse response = client.search(Patient.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, patientId); + } } @Test - public void testCARINBlueButton_ExplanationOfBenefit_Created_SearchParameter() { - // Name: CARINBlueButton_ExplanationOfBenefit_Created_SearchParameter + public void testOrganizationId() throws Exception { + if (!skip) { + // A common call -> GET [base]/Organization?_id=[id],[id],[id] + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("_id", String.join(",", organizationId, organizationOrg1Id, organizationOrg45Id)); + FHIRResponse response = client.search(Organization.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, organizationId); + } + } - /* - * "code": "status", "base": ["ExplanationOfBenefit"], "type": "date", "expression": - * "explanationofbenefit.created", "xpath": "f:explanationofbenefit/f:created", - */ + @Test + public void testCoverageIdWithInclude() throws Exception { + if (!skip) { + // A common call -> GET [base]/Coverage?_id=[id]&_include=Coverage:payor + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("_id", coverageId); + parameters.searchParam("_include", "Coverage:payor"); + FHIRResponse response = client.search(Coverage.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, coverageId, organizationOrg45Id); + } } @Test - public void testCARINBlueButton_ExplanationOfBenefit_Patient_SearchParameter() { - // Name: CARINBlueButton_ExplanationOfBenefit_Created_SearchParameter + public void testExplanationOfBenefitId() throws Exception { + if (!skip) { + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("_id", explanationOfBenefitId); + FHIRResponse response = client.search(ExplanationOfBenefit.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, explanationOfBenefitId); + } + } - /* - * "code": "patient", "base": ["ExplanationOfBenefit"], "type": "reference", "expression": - * "explanationofbenefit.patient", "xpath": "f:explanationofbenefit/f:patient", - */ + @Test + public void testExplanationOfBenefitIdentifierNoSystem() throws Exception { + if (!skip) { + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("identifier", "|4E93-BE91-EAC1977941A8"); + FHIRResponse response = client.search(ExplanationOfBenefit.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, explanationOfBenefitId); + } + } + + @Test + public void testExplanationOfBenefitIdentifierWithSystem() throws Exception { + if (!skip) { + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("identifier", "http://www.bcbs.com/fhir/ns/NamingSystem/explanationOfBenefit-identifier|4E93-BE91-EAC1977941A8"); + FHIRResponse response = client.search(ExplanationOfBenefit.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, explanationOfBenefitId); + } + } + + @Test + public void testCARINBlueButton_ExplanationOfBenefit_Patient_SearchParameter() throws Exception { + if (!skip) { + // This is now enabled due to HL7 FHIR Jira - https://jira.hl7.org/browse/FHIR-27739 + // https://github.com/IBM/FHIR/issues/1157 + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("patient", "Patient/Patient1"); + FHIRResponse response = client.search(ExplanationOfBenefit.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, explanationOfBenefitId); + } + } + + @Test + public void testExplanationOfBenefitLastUpdated() throws Exception { + if (!skip) { + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("_lastUpdated", "le1990"); + FHIRResponse response = client.search(ExplanationOfBenefit.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() == 0); + + parameters = new FHIRParameters(); + parameters.searchParam("_lastUpdated", "ge1990"); + response = client.search(ExplanationOfBenefit.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, explanationOfBenefitId); + } + } + + @Test + public void testCARINBlueButton_Coverage_Patient_SearchParameter() throws Exception { + // Name: CARINBlueButton_Coverage_Patient_SearchParameter + if (!skip) { + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("patient", "Patient/Patient1"); + FHIRResponse response = client.search(Coverage.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, coverageId); + } + } + + @Test + public void testCARINBlueButton_ExplanationOfBenefit_Created_SearchParameter() throws Exception { + // Enabled per https://jira.hl7.org/browse/FHIR-27738 and https://github.com/IBM/FHIR/issues/1156 + // Name: CARINBlueButton_ExplanationOfBenefit_Created_SearchParameter (note it uses the created code in the + // spec) + // The Search Parameter embedded in the spec had a bad code, should be 'created'. + if (!skip) { + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("created", "ge2017-04-15"); + FHIRResponse response = client.search(ExplanationOfBenefit.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, explanationOfBenefitId); + } + } + + @Test + public void testComplicatedInclude() throws Exception { + if (!skip) { + /* This example is per: + * https://confluence.hl7.org/pages/viewpage.action?pageId=82911348&preview=/82911348/82911352/CARIN%20BB% + * 20RESTful%20API%20Combined%20-%20FHIR-26702%20-%20FHIR-26693%200513%202020.docx RESTFUL API SHALL + */ + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("patient", "Patient/Patient1"); + parameters.searchParam("_lastUpdated", "ge2020"); + parameters.searchParam("_include", "ExplanationOfBenefit:patient"); + parameters.searchParam("_include", "ExplanationOfBenefit:provider"); + parameters.searchParam("_include", "ExplanationOfBenefit:care-team"); + parameters.searchParam("_include", "ExplanationOfBenefit:coverage"); + // https://github.com/IBM/FHIR/issues/1158 + // parameters.searchParam("_include:iterate", "PractitionerRole:practitioner"); + // parameters.searchParam("_include:iterate", "PractitionerRole:organization"); + // parameters.searchParam("_include:iterate", "Coverage:payor"); + + FHIRResponse response = client.search(ExplanationOfBenefit.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, explanationOfBenefitId); + } + } + + @Test(enabled = false) + public void testExplanationOfBenefitServiceDate() throws Exception { + if (!skip) { + /* + * This should be coming in a new CARIN BB Rev. + * https://confluence.hl7.org/pages/viewpage.action?pageId=82911348&preview=/82911348/82911352/CARIN%20BB% + * 20RESTful%20API%20Combined%20-%20FHIR-26702%20-%20FHIR-26693%200513%202020.docx RESTFUL API SHALL + * service-date date GET [base]/ExplanationOfBenefit?service-date=[prefix][date] Shall only be supported in + * a combination with patient + */ + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("service-date", "ge2014"); + FHIRResponse response = client.search(ExplanationOfBenefit.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, explanationOfBenefitId); + } + } + + @Test(enabled = false) + public void testExplanationOfBenefitType() throws Exception { + if (!skip) { + /* + * This should be coming in a new CARIN BB Rev. + * https://confluence.hl7.org/pages/viewpage.action?pageId=82911348&preview=/82911348/82911352/CARIN%20BB% + * 20RESTful%20API%20Combined%20-%20FHIR-26702%20-%20FHIR-26693%200513%202020.docx RESTFUL API SHALL type + * token GET [base]/ExplanationOfBenefit?type=[system]|[code] Shall only be supported in a combination with + * patient + */ + FHIRParameters parameters = new FHIRParameters(); + parameters.searchParam("type", "http://hl7.org/fhir/us/carin/CodeSystem/carin-bb-claim-type|inpatient-facility"); + FHIRResponse response = client.search(ExplanationOfBenefit.class.getSimpleName(), parameters); + assertSearchResponse(response, Response.Status.OK.getStatusCode()); + Bundle bundle = response.getResource(Bundle.class); + assertNotNull(bundle); + assertTrue(bundle.getEntry().size() >= 1); + assertContainsIds(bundle, explanationOfBenefitId); + } } } \ No newline at end of file diff --git a/fhir-server-test/src/test/java/com/ibm/fhir/server/test/profiles/ProfilesTestBase.java b/fhir-server-test/src/test/java/com/ibm/fhir/server/test/profiles/ProfilesTestBase.java index 02a11ad890c..81e1144ef21 100644 --- a/fhir-server-test/src/test/java/com/ibm/fhir/server/test/profiles/ProfilesTestBase.java +++ b/fhir-server-test/src/test/java/com/ibm/fhir/server/test/profiles/ProfilesTestBase.java @@ -7,6 +7,8 @@ package com.ibm.fhir.server.test.profiles; import static org.testng.Assert.assertTrue; +import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.assertNotNull; import java.util.Collection; import java.util.List; @@ -15,21 +17,27 @@ import org.testng.annotations.BeforeClass; +import com.ibm.fhir.client.FHIRResponse; +import com.ibm.fhir.model.resource.Bundle; import com.ibm.fhir.model.resource.CapabilityStatement; +import com.ibm.fhir.model.resource.OperationOutcome; import com.ibm.fhir.path.FHIRPathNode; import com.ibm.fhir.path.evaluator.FHIRPathEvaluator; import com.ibm.fhir.path.evaluator.FHIRPathEvaluator.EvaluationContext; +import com.ibm.fhir.path.exception.FHIRPathException; import com.ibm.fhir.server.test.FHIRServerTestBase; +import com.ibm.fhir.server.test.SearchAllTest; /* - * This class is not designed to run its own. The class does the basic lift to check: - *
  • is the profile valid to run on the server? + * This class is not designed to run its own. The class does the basic lift to check: + *
  • is the profile valid to run on the server? */ public abstract class ProfilesTestBase extends FHIRServerTestBase { private static final String CLASSNAME = ProfilesTestBase.class.getName(); private static final Logger logger = Logger.getLogger(CLASSNAME); public static final String EXPRESSION_PROFILES = "rest.resource.supportedProfile"; + public static final String EXPRESSION_BUNDLE_IDS = "entry.resource.id"; public Boolean check = Boolean.TRUE; public Boolean skip = Boolean.FALSE; @@ -46,6 +54,33 @@ public void setCheck(Boolean check) { this.check = check; } + /** + * checks that the bundle contains resources with the given ids. + * @param bundle + * @param ids + * @throws FHIRPathException + */ + public static void assertContainsIds(Bundle bundle, String... ids) throws FHIRPathException { + FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator(); + EvaluationContext evaluationContext = new EvaluationContext(bundle); + Collection tmpResults = evaluator.evaluate(evaluationContext, EXPRESSION_BUNDLE_IDS); + Collection listOfIds = tmpResults.stream().map(x -> x.toString()).collect(Collectors.toList()); + System.out.println(listOfIds); + for(String id : ids) { + System.out.println(id); + assertTrue(listOfIds.contains(id)); + } + } + + public void assertSearchResponse(FHIRResponse response, int expectedStatusCode) throws Exception { + assertNotNull(response); + if (expectedStatusCode != response.getStatus()) { + OperationOutcome operationOutcome = response.getResource(OperationOutcome.class); + SearchAllTest.generateOutput(operationOutcome); + } + assertEquals(expectedStatusCode, response.getStatus()); + } + @BeforeClass public void checkProfileExistsOnServer() throws Exception { CapabilityStatement conf = retrieveConformanceStatement(); @@ -53,8 +88,7 @@ public void checkProfileExistsOnServer() throws Exception { EvaluationContext evaluationContext = new EvaluationContext(conf); // All the possible required profiles Collection tmpResults = evaluator.evaluate(evaluationContext, EXPRESSION_PROFILES); - Collection listOfProfiles = tmpResults.stream().map( x -> x.getValue().asStringValue().string()).collect(Collectors.toList()); - System.out.println(listOfProfiles); + Collection listOfProfiles = tmpResults.stream().map(x -> x.getValue().asStringValue().string()).collect(Collectors.toList()); for(String requiredProfile : getRequiredProfiles()) { boolean v = listOfProfiles.contains(requiredProfile); if(!v && check) {