package ca.uhn.fhir.jpa.provider; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.stringContainsInOrder; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import java.io.IOException; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.AfterClass; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.springframework.transaction.annotation.Transactional; import ca.uhn.fhir.model.dstu2.composite.CodingDt; import ca.uhn.fhir.model.dstu2.resource.Parameters; import ca.uhn.fhir.model.dstu2.resource.ValueSet; import ca.uhn.fhir.model.primitive.BooleanDt; import ca.uhn.fhir.model.primitive.CodeDt; import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.model.primitive.UriDt; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.util.TestUtil; public class ResourceProviderDstu2ValueSetTest extends BaseResourceProviderDstu2Test { private IIdType myExtensionalVsId; private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderDstu2ValueSetTest.class); @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); } @Before @Transactional public void before02() throws IOException { ValueSet upload = loadResourceFromClasspath(ValueSet.class, "/extensional-case-2.xml"); upload.setId(""); myExtensionalVsId = myValueSetDao.create(upload, mySrd).getId().toUnqualifiedVersionless(); } @Test public void testValidateCodeOperationByCodeAndSystemInstance() { //@formatter:off Parameters respParam = ourClient .operation() .onInstance(myExtensionalVsId) .named("validate-code") .withParameter(Parameters.class, "code", new CodeDt("8495-4")) .andParameter("system", new UriDt("http://loinc.org")) .execute(); //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam); ourLog.info(resp); assertEquals(new BooleanDt(true), respParam.getParameter().get(0).getValue()); } @Test public void testValidateCodeOperationByCodeAndSystemType() { //@formatter:off Parameters respParam = ourClient .operation() .onType(ValueSet.class) .named("validate-code") .withParameter(Parameters.class, "code", new CodeDt("8450-9")) .andParameter("system", new UriDt("http://loinc.org")) .execute(); //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam); ourLog.info(resp); assertEquals(new BooleanDt(true), respParam.getParameter().get(0).getValue()); } @Test public void testLookupOperationByCodeAndSystem() { //@formatter:off Parameters respParam = ourClient .operation() .onType(ValueSet.class) .named("lookup") .withParameter(Parameters.class, "code", new CodeDt("8450-9")) .andParameter("system", new UriDt("http://loinc.org")) .execute(); //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam); ourLog.info(resp); assertEquals("name", respParam.getParameter().get(0).getName()); assertEquals(new StringDt("Unknown"), respParam.getParameter().get(0).getValue()); assertEquals("display", respParam.getParameter().get(1).getName()); assertEquals(new StringDt("Systolic blood pressure--expiration"), respParam.getParameter().get(1).getValue()); assertEquals("abstract", respParam.getParameter().get(2).getName()); assertEquals(new BooleanDt(false), respParam.getParameter().get(2).getValue()); } @Test @Ignore public void testLookupOperationForBuiltInCode() { //@formatter:off Parameters respParam = ourClient .operation() .onType(ValueSet.class) .named("lookup") .withParameter(Parameters.class, "code", new CodeDt("M")) .andParameter("system", new UriDt("http://hl7.org/fhir/v3/MaritalStatus")) .execute(); //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam); ourLog.info(resp); assertEquals("name", respParam.getParameter().get(0).getName()); assertEquals(new StringDt("Unknown"), respParam.getParameter().get(0).getValue()); assertEquals("display", respParam.getParameter().get(1).getName()); assertEquals(new StringDt("Married"), respParam.getParameter().get(1).getValue()); assertEquals("abstract", respParam.getParameter().get(2).getName()); assertEquals(new BooleanDt(false), respParam.getParameter().get(2).getValue()); } @Test public void testLookupOperationByCoding() { //@formatter:off Parameters respParam = ourClient .operation() .onType(ValueSet.class) .named("lookup") .withParameter(Parameters.class, "coding", new CodingDt("http://loinc.org", "8450-9")) .execute(); //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(respParam); ourLog.info(resp); assertEquals("name", respParam.getParameter().get(0).getName()); assertEquals(new StringDt("Unknown"), respParam.getParameter().get(0).getValue()); assertEquals("display", respParam.getParameter().get(1).getName()); assertEquals(new StringDt("Systolic blood pressure--expiration"), respParam.getParameter().get(1).getValue()); assertEquals("abstract", respParam.getParameter().get(2).getName()); assertEquals(new BooleanDt(false), respParam.getParameter().get(2).getValue()); } @Test public void testLookupOperationByInvalidCombination() { //@formatter:off try { ourClient .operation() .onType(ValueSet.class) .named("lookup") .withParameter(Parameters.class, "coding", new CodingDt("http://loinc.org", "8450-9")) .andParameter("code", new CodeDt("8450-9")) .andParameter("system", new UriDt("http://loinc.org")) .execute(); fail(); } catch (InvalidRequestException e) { assertEquals("HTTP 400 Bad Request: $lookup can only validate (system AND code) OR (coding.system AND coding.code)", e.getMessage()); } //@formatter:on } @Test public void testLookupOperationByInvalidCombination2() { //@formatter:off try { ourClient .operation() .onType(ValueSet.class) .named("lookup") .withParameter(Parameters.class, "coding", new CodingDt("http://loinc.org", "8450-9")) .andParameter("system", new UriDt("http://loinc.org")) .execute(); fail(); } catch (InvalidRequestException e) { assertEquals("HTTP 400 Bad Request: $lookup can only validate (system AND code) OR (coding.system AND coding.code)", e.getMessage()); } //@formatter:on } @Test public void testLookupOperationByInvalidCombination3() { //@formatter:off try { ourClient .operation() .onType(ValueSet.class) .named("lookup") .withParameter(Parameters.class, "coding", new CodingDt("http://loinc.org", null)) .execute(); fail(); } catch (InvalidRequestException e) { assertEquals("HTTP 400 Bad Request: No code, coding, or codeableConcept provided to validate", e.getMessage()); } //@formatter:on } @Test public void testExpandById() throws IOException { //@formatter:off Parameters respParam = ourClient .operation() .onInstance(myExtensionalVsId) .named("expand") .withNoParameters(Parameters.class) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); // @formatter:off assertThat(resp, stringContainsInOrder("<ValueSet xmlns=\"http://hl7.org/fhir\">", "<expansion>", "<contains>", "<system value=\"http://loinc.org\"/>", "<code value=\"11378-7\"/>", "<display value=\"Systolic blood pressure at First encounter\"/>", "</contains>", "<contains>", "<system value=\"http://loinc.org\"/>", "<code value=\"8450-9\"/>", "<display value=\"Systolic blood pressure--expiration\"/>", "</contains>", "</expansion>" )); //@formatter:on /* * Filter with display name */ //@formatter:off respParam = ourClient .operation() .onInstance(myExtensionalVsId) .named("expand") .withParameter(Parameters.class, "filter", new StringDt("systolic")) .execute(); expanded = (ValueSet) respParam.getParameter().get(0).getResource(); //@formatter:on expanded = myValueSetDao.expand(myExtensionalVsId, ("systolic"), mySrd); resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); //@formatter:off assertThat(resp, stringContainsInOrder( "<code value=\"11378-7\"/>", "<display value=\"Systolic blood pressure at First encounter\"/>")); //@formatter:on /* * Filter with code */ //@formatter:off respParam = ourClient .operation() .onInstance(myExtensionalVsId) .named("expand") .withParameter(Parameters.class, "filter", new StringDt("11378")) .execute(); expanded = (ValueSet) respParam.getParameter().get(0).getResource(); //@formatter:on resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); //@formatter:off assertThat(resp, stringContainsInOrder( "<code value=\"11378-7\"/>", "<display value=\"Systolic blood pressure at First encounter\"/>")); //@formatter:on } @Test public void testExpandByIdentifier() { //@formatter:off Parameters respParam = ourClient .operation() .onType(ValueSet.class) .named("expand") .withParameter(Parameters.class, "identifier", new UriDt("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2")) .andParameter("filter", new StringDt("11378")) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); //@formatter:off assertThat(resp, stringContainsInOrder( "<code value=\"11378-7\"/>", "<display value=\"Systolic blood pressure at First encounter\"/>")); //@formatter:on assertThat(resp, not(containsString("<code value=\"8450-9\"/>"))); } @Test public void testExpandByValueSet() throws IOException { ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-2.xml"); //@formatter:off Parameters respParam = ourClient .operation() .onType(ValueSet.class) .named("expand") .withParameter(Parameters.class, "valueSet", toExpand) .andParameter("filter", new StringDt("11378")) .execute(); ValueSet expanded = (ValueSet) respParam.getParameter().get(0).getResource(); //@formatter:on String resp = myFhirCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(expanded); ourLog.info(resp); //@formatter:off assertThat(resp, stringContainsInOrder( "<code value=\"11378-7\"/>", "<display value=\"Systolic blood pressure at First encounter\"/>")); //@formatter:on assertThat(resp, not(containsString("<code value=\"8450-9\"/>"))); } @Test public void testExpandInvalidParams() throws IOException { //@formatter:off try { ourClient .operation() .onType(ValueSet.class) .named("expand") .withNoParameters(Parameters.class) .execute(); fail(); } catch (InvalidRequestException e) { assertEquals("HTTP 400 Bad Request: $expand operation at the type level (no ID specified) requires an identifier or a valueSet as a part of the request", e.getMessage()); } //@formatter:on //@formatter:off try { ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-2.xml"); ourClient .operation() .onType(ValueSet.class) .named("expand") .withParameter(Parameters.class, "valueSet", toExpand) .andParameter("identifier", new UriDt("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2")) .execute(); fail(); } catch (InvalidRequestException e) { assertEquals("HTTP 400 Bad Request: $expand must EITHER be invoked at the type level, or have an identifier specified, or have a ValueSet specified. Can not combine these options.", e.getMessage()); } //@formatter:on //@formatter:off try { ValueSet toExpand = loadResourceFromClasspath(ValueSet.class, "/extensional-case-2.xml"); ourClient .operation() .onInstance(myExtensionalVsId) .named("expand") .withParameter(Parameters.class, "valueSet", toExpand) .andParameter("identifier", new UriDt("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2")) .execute(); fail(); } catch (InvalidRequestException e) { assertEquals("HTTP 400 Bad Request: $expand must EITHER be invoked at the type level, or have an identifier specified, or have a ValueSet specified. Can not combine these options.", e.getMessage()); } //@formatter:on } }