From dbc6abc6583f36b6307867e80c0b4764e45885e6 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Fri, 13 Jan 2017 21:46:16 -0600 Subject: [PATCH] Fix #504 - Error if custom type has illegal extensions --- .../context/BaseRuntimeElementDefinition.java | 11 ++-- .../ca/uhn/fhir/context/ModelScanner.java | 22 ++++--- .../context/RuntimeResourceDefinition.java | 1 + .../uhn/fhir/parser/XmlParserDstu2Test.java | 61 ------------------- .../fhir/context/ModelScannerDstu3Test.java | 59 ++++++++++++------ src/changes/changes.xml | 6 ++ 6 files changed, 67 insertions(+), 93 deletions(-) diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeElementDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeElementDefinition.java index 7c856d2d449..e4107a028c0 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeElementDefinition.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeElementDefinition.java @@ -21,11 +21,7 @@ package ca.uhn.fhir.context; */ import java.lang.reflect.Constructor; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import org.apache.commons.lang3.StringUtils; import org.hl7.fhir.instance.model.api.IBase; @@ -136,6 +132,11 @@ public abstract class BaseRuntimeElementDefinition { return myName; } + public boolean hasExtensions() { + validateSealed(); + return myExtensions.size() > 0; + } + public boolean isStandardType() { return myStandardType; } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java index 290b22738d4..e2873b67c03 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/ModelScanner.java @@ -32,15 +32,7 @@ import java.util.*; import java.util.Map.Entry; import org.apache.commons.io.IOUtils; -import org.hl7.fhir.instance.model.api.IBase; -import org.hl7.fhir.instance.model.api.IBaseBackboneElement; -import org.hl7.fhir.instance.model.api.IBaseDatatype; -import org.hl7.fhir.instance.model.api.IBaseDatatypeElement; -import org.hl7.fhir.instance.model.api.IBaseResource; -import org.hl7.fhir.instance.model.api.IBaseXhtml; -import org.hl7.fhir.instance.model.api.ICompositeType; -import org.hl7.fhir.instance.model.api.IIdType; -import org.hl7.fhir.instance.model.api.IPrimitiveType; +import org.hl7.fhir.instance.model.api.*; import ca.uhn.fhir.model.api.ExtensionDt; import ca.uhn.fhir.model.api.IDatatype; @@ -391,6 +383,18 @@ class ModelScanner { */ resourceDef.populateScanAlso(myScanAlso); + /* + * See #504: + * Bundle types may not have extensions + */ + if (resourceDef.hasExtensions()) { + if (IAnyResource.class.isAssignableFrom(theClass)) { + if (!IDomainResource.class.isAssignableFrom(theClass)) { + throw new ConfigurationException("Class \"" + theClass + "\" is invalid. This resource type is not a DomainResource, it must not have extensions"); + } + } + } + return resourceName; } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeResourceDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeResourceDefinition.java index 5b21d577df4..16f72f5acde 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeResourceDefinition.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/RuntimeResourceDefinition.java @@ -229,4 +229,5 @@ public class RuntimeResourceDefinition extends BaseRuntimeElementCompositeDefini return retVal; } + } diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2Test.java index d38c9764441..441acc63334 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/XmlParserDstu2Test.java @@ -7,7 +7,6 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.stringContainsInOrder; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; @@ -34,7 +33,6 @@ import org.hl7.fhir.instance.model.api.IBaseResource; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.internal.stubbing.answers.ThrowsException; @@ -45,8 +43,6 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.api.*; import ca.uhn.fhir.model.api.Bundle; import ca.uhn.fhir.model.api.annotation.Child; -import ca.uhn.fhir.model.api.annotation.Description; -import ca.uhn.fhir.model.api.annotation.Extension; import ca.uhn.fhir.model.api.annotation.ResourceDef; import ca.uhn.fhir.model.base.composite.BaseCodingDt; import ca.uhn.fhir.model.dstu2.composite.*; @@ -2782,61 +2778,4 @@ public class XmlParserDstu2Test { } } - - /** - * See #504 - */ - @Test - @Ignore - public void testBinaryEncodingWithKnownExtension() { - LetterTemplate template = new LetterTemplate(); - template.setName(new StringDt("Testname")); - template.setContentType(new CodeDt("test-type")); - - IParser parser = FhirContext.forDstu2().newJsonParser(); - String resourceToString = parser.encodeResourceToString(template); - LetterTemplate resource = parser.parseResource(LetterTemplate.class, resourceToString); - assertNotNull(resource.getContentType()); - assertNotNull(resource.getName()); - } - - /** - * See #504 - */ - @Test - @Ignore - public void testBinaryEncodingWithUnknownExtension() { - Binary template = new Binary(); - String extensionURL = "http://www.something.org/StructureDefinition/letter-template"; - ExtensionDt e = new ExtensionDt(false, extensionURL, new StringDt("Testname")); - template.getUndeclaredExtensions().add(e); - template.setContentType(new CodeDt("test-type")); - - IParser parser = FhirContext.forDstu2().newJsonParser(); - String resourceToString = parser.encodeResourceToString(template); - Binary resource = parser.parseResource(Binary.class, resourceToString); - assertNotNull(resource.getContentType()); - assertFalse((resource.getUndeclaredExtensionsByUrl(extensionURL).isEmpty())); - assertNotNull(resource.getUndeclaredExtensionsByUrl(extensionURL).get(0)); - } - - @ResourceDef(name = "Binary", id = "letter-template", profile = "http://www.something.org/StructureDefinition/letter-template") - public static class LetterTemplate extends Binary { - - @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; - } - } - } diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/context/ModelScannerDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/context/ModelScannerDstu3Test.java index 6b9e9bec1f6..d699828d2a8 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/context/ModelScannerDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/context/ModelScannerDstu3Test.java @@ -6,26 +6,14 @@ import static org.junit.Assert.fail; import java.util.List; -import org.hl7.fhir.dstu3.model.BaseResource; -import org.hl7.fhir.dstu3.model.CarePlan; -import org.hl7.fhir.dstu3.model.CodeType; -import org.hl7.fhir.dstu3.model.IdType; -import org.hl7.fhir.dstu3.model.Meta; -import org.hl7.fhir.dstu3.model.Patient; -import org.hl7.fhir.dstu3.model.Property; -import org.hl7.fhir.dstu3.model.Resource; -import org.hl7.fhir.dstu3.model.ResourceType; -import org.hl7.fhir.instance.model.api.IAnyResource; -import org.hl7.fhir.instance.model.api.IBaseMetaType; -import org.hl7.fhir.instance.model.api.IIdType; -import org.hl7.fhir.instance.model.api.IPrimitiveType; +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.Compartment; -import ca.uhn.fhir.model.api.annotation.ResourceDef; -import ca.uhn.fhir.model.api.annotation.SearchParamDefinition; +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; @@ -40,11 +28,10 @@ public class ModelScannerDstu3Test { 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 { @@ -225,4 +212,40 @@ public class ModelScannerDstu3Test { } + /** + * 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; + } + } + } diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 07e01307af4..ed5f8380f53 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -198,6 +198,12 @@ wrong type (string instead of token). Thanks to Robert Lichtenberger for reporting! + + Custom resource types which extend Binary must not + have declared extensions since this is invalid in + FHIR (and HAPI would just ignore them anyhow). Thanks + to Thomas S Berg for reporting! +