package ca.uhn.fhir.context; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import java.util.List; import org.hl7.fhir.dstu3.model.*; import org.junit.AfterClass; import org.junit.Ignore; import org.junit.Test; import ca.uhn.fhir.model.api.annotation.*; import ca.uhn.fhir.model.api.annotation.Extension; import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.util.TestUtil; public class ModelScannerDstu3Test { @AfterClass public static void afterClassClearContext() { TestUtil.clearAllStaticFieldsForUnitTest(); } @Test public void testScanBundle() { FhirContext ctx = FhirContext.forDstu3(); RuntimeResourceDefinition def = ctx.getResourceDefinition("Bundle"); assertNotNull(def.getSearchParam("composition")); assertNotNull(def.getSearchParam("_id")); } @Test public void testBundleMustImplementIBaseBundle() throws DataFormatException { FhirContext ctx = FhirContext.forDstu3(); try { ctx.getResourceDefinition(MyBundle.class); fail(); } catch (ConfigurationException e) { assertEquals("Resource type declares resource name Bundle but does not implement IBaseBundle", e.getMessage()); } } /** This failed at one point */ @Test public void testCarePlan() throws DataFormatException { FhirContext.forDstu3().getResourceDefinition(CarePlan.class); } @Test public void testExtendedClass() { FhirContext ctx = FhirContext.forDstu3(); ctx.getResourceDefinition(MyPatient.class); RuntimeResourceDefinition patient = ctx.getResourceDefinition("Patient"); assertEquals(Patient.class, patient.getImplementingClass()); RuntimeResourceDefinition def = ctx.getResourceDefinition(MyPatient.class); RuntimeResourceDefinition baseDef = def.getBaseDefinition(); assertEquals(Patient.class, baseDef.getImplementingClass()); } @Test public void testResourceWithNoDef() { try { FhirContext.forDstu3().getResourceDefinition(NoResourceDef.class); fail(); } catch (ConfigurationException e) { assertEquals("Resource class[ca.uhn.fhir.context.ModelScannerDstu3Test$NoResourceDef] does not contain any valid HAPI-FHIR annotations", e.getMessage()); } } @Test public void testScanExtensionTypes() throws DataFormatException { FhirContext ctx = FhirContext.forDstu3(); RuntimeResourceDefinition def = ctx.getResourceDefinition(ResourceWithExtensionsDstu3A.class); assertEquals(RuntimeChildCompositeDatatypeDefinition.class, def.getChildByNameOrThrowDataFormatException("identifier").getClass()); RuntimeChildDeclaredExtensionDefinition ext = def.getDeclaredExtension("http://foo/#f1", ""); assertNotNull(ext); BaseRuntimeElementDefinition<?> valueString = ext.getChildByName("valueString"); assertNotNull(valueString); ext = def.getDeclaredExtension("http://foo/#f2", ""); assertNotNull(ext); valueString = ext.getChildByName("valueString"); assertNotNull(valueString); ext = def.getDeclaredExtension("http://bar/#b1", ""); assertNotNull(ext); RuntimeChildDeclaredExtensionDefinition childExt = ext.getChildExtensionForUrl("http://bar/#b1/1"); assertNotNull(childExt); BaseRuntimeElementDefinition<?> valueDate = childExt.getChildByName("valueDate"); assertNotNull(valueDate); childExt = ext.getChildExtensionForUrl("http://bar/#b1/2"); assertNotNull(childExt); childExt = childExt.getChildExtensionForUrl("http://bar/#b1/2/1"); assertNotNull(childExt); valueDate = childExt.getChildByName("valueDate"); assertNotNull(valueDate); } /** * TODO: Re-enable this when Claim's compartment defs are cleaned up */ @Test @Ignore public void testSearchParamWithCompartmentForNonReferenceParam() { try { FhirContext.forDstu3().getResourceDefinition(CompartmentForNonReferenceParam.class); fail(); } catch (ConfigurationException e) { assertEquals("Search param foo provides compartment membershit but is not of type 'reference'", e.getMessage()); } } @Test public void testSearchParamWithInvalidType() { try { FhirContext.forDstu3().getResourceDefinition(InvalidParamType.class); fail(); } catch (ConfigurationException e) { assertEquals("Search param foo has an invalid type: bar", e.getMessage()); } } @ResourceDef(name = "Patient") public static class CompartmentForNonReferenceParam extends Patient { private static final long serialVersionUID = 1L; @SearchParamDefinition(name = "foo", path = "Patient.telecom", type = "string", providesMembershipIn = { @Compartment(name = "Patient"), @Compartment(name = "Device") }) public static final String SP_TELECOM = "foo"; } @ResourceDef(name = "Patient") public static class InvalidParamType extends Patient { private static final long serialVersionUID = 1L; @SearchParamDefinition(name = "foo", path = "Patient.telecom", type = "bar") public static final String SP_TELECOM = "foo"; } @ResourceDef(name = "Bundle") public static class MyBundle extends Resource { private static final long serialVersionUID = 1L; @Override public String fhirType() { return null; } @Override public String getId() { return null; } @Override public IdType getIdElement() { return null; } @Override public CodeType getLanguageElement() { return null; } @Override public Meta getMeta() { return null; } @Override protected void listChildren(List<Property> theResult) { // nothing } @Override public Resource setId(String theId) { return null; } @Override public Resource setIdElement(IdType theIdType) { return null; } @Override public Resource copy() { return null; } @Override public ResourceType getResourceType() { return null; } } class NoResourceDef extends Patient { private static final long serialVersionUID = 1L; @SearchParamDefinition(name = "foo", path = "Patient.telecom", type = "bar") public static final String SP_TELECOM = "foo"; } /** * See #504 */ @Test public void testBinaryMayNotHaveExtensions() { FhirContext ctx = FhirContext.forDstu3(); try { ctx.getResourceDefinition(LetterTemplate.class); fail(); } catch (ConfigurationException e) { assertEquals("Class \"class ca.uhn.fhir.context.ModelScannerDstu3Test$LetterTemplate\" is invalid. This resource type is not a DomainResource, it must not have extensions", e.getMessage()); } } @ResourceDef(name = "Binary", id = "letter-template", profile = "http://www.something.org/StructureDefinition/letter-template") public static class LetterTemplate extends Binary { private static final long serialVersionUID = 1L; @Child(name = "name") @Extension(url = "http://example.com/dontuse#name", definedLocally = false, isModifier = false) @Description(shortDefinition = "The name of the template") private StringDt myName; public LetterTemplate() { } public void setName(StringDt name) { myName = name; } public StringDt getName() { return myName; } } }