From 38d30eef492ddac1672f70932ae35b1f765486b0 Mon Sep 17 00:00:00 2001 From: James Agnew Date: Wed, 29 Jun 2016 10:26:36 -0400 Subject: [PATCH] Respect order for order=REPLACE_PARENT --- ...BaseRuntimeElementCompositeDefinition.java | 9 ++- .../FooMessageHeaderWithExplicitField.java | 58 +++++++++++++++++++ .../uhn/fhir/parser/XmlParserDstu3Test.java | 30 +++++++++- src/changes/changes.xml | 7 +++ 4 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/FooMessageHeaderWithExplicitField.java diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeElementCompositeDefinition.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeElementCompositeDefinition.java index d8e6a27d4f0..11f4743c219 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeElementCompositeDefinition.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/BaseRuntimeElementCompositeDefinition.java @@ -245,14 +245,17 @@ public abstract class BaseRuntimeElementCompositeDefinition ext String elementName = childAnnotation.name(); int order = childAnnotation.order(); boolean childIsChoiceType = false; + boolean orderIsReplaceParent = false; + if (order == Child.REPLACE_PARENT) { - + if (extensionAttr != null) { for (Entry nextEntry : orderMap.entrySet()) { BaseRuntimeDeclaredChildDefinition nextDef = nextEntry.getValue(); if (nextDef instanceof RuntimeChildDeclaredExtensionDefinition) { if (nextDef.getExtensionUrl().equals(extensionAttr.url())) { + orderIsReplaceParent = true; order = nextEntry.getKey(); orderMap.remove(nextEntry.getKey()); elementNames.remove(elementName); @@ -270,6 +273,7 @@ public abstract class BaseRuntimeElementCompositeDefinition ext for (Entry nextEntry : orderMap.entrySet()) { BaseRuntimeDeclaredChildDefinition nextDef = nextEntry.getValue(); if (elementName.equals(nextDef.getElementName())) { + orderIsReplaceParent = true; order = nextEntry.getKey(); BaseRuntimeDeclaredChildDefinition existing = orderMap.remove(nextEntry.getKey()); elementNames.remove(elementName); @@ -297,7 +301,8 @@ public abstract class BaseRuntimeElementCompositeDefinition ext if (order < 0 && order != Child.ORDER_UNKNOWN) { throw new ConfigurationException("Invalid order '" + order + "' on @Child for field '" + next.getName() + "' on target type: " + theClass); } - if (order != Child.ORDER_UNKNOWN) { + + if (order != Child.ORDER_UNKNOWN && !orderIsReplaceParent) { order = order + baseElementOrder; } // int min = childAnnotation.min(); diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/FooMessageHeaderWithExplicitField.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/FooMessageHeaderWithExplicitField.java new file mode 100644 index 00000000000..184fd144559 --- /dev/null +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/FooMessageHeaderWithExplicitField.java @@ -0,0 +1,58 @@ +package ca.uhn.fhir.parser; + +import org.hl7.fhir.dstu3.exceptions.FHIRException; +import org.hl7.fhir.dstu3.model.Identifier; +import org.hl7.fhir.dstu3.model.MessageHeader; + +import ca.uhn.fhir.model.api.annotation.Block; +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; + +@ResourceDef(name = "FooMessageHeader") +public class FooMessageHeaderWithExplicitField extends MessageHeader { + + private static final long serialVersionUID = 1L; + + /** + * The source application from which this message originated. + */ + @Child(name = "source", type = {}, order = Child.REPLACE_PARENT, min = 1, max = 1, modifier = false, summary = true) + @Description(shortDefinition = "Message Source Application", formalDefinition = "The source application from which this message originated.") + protected FooMessageSourceComponent source; + + public void setSourceNew(FooMessageSourceComponent theSource) { + source = theSource; + } + + @Block() + public static class FooMessageSourceComponent extends MessageHeader.MessageSourceComponent { + + private static final long serialVersionUID = 1L; + @Child(name = "ext-messageheader-application-id", type = Identifier.class, modifier = true) + @Description(shortDefinition = "Message Header Application ID") + @Extension(url = "http://foo", definedLocally = false, isModifier = false) + private Identifier messageHeaderApplicationId; + + /* + * Get messageHeaderApplicationId + */ + public Identifier getMessageHeaderApplicationId() throws FHIRException { + + if (messageHeaderApplicationId == null) { + messageHeaderApplicationId = new Identifier(); + } + return messageHeaderApplicationId; + } + + /* + * Set messageHeaderApplicationId + */ + public void setmessageHeaderApplicationId(Identifier messageHeaderApplicationId) { + this.messageHeaderApplicationId = messageHeaderApplicationId; + } + + } + +} \ No newline at end of file diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/XmlParserDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/XmlParserDstu3Test.java index c450d65b78d..fb69576c935 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/XmlParserDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/XmlParserDstu3Test.java @@ -34,7 +34,6 @@ import org.custommonkey.xmlunit.XMLUnit; import org.hamcrest.collection.IsEmptyCollection; import org.hamcrest.core.StringContains; import org.hamcrest.text.StringContainsInOrder; -import org.hl7.fhir.dstu3.exceptions.FHIRException; import org.hl7.fhir.dstu3.model.Address.AddressUse; import org.hl7.fhir.dstu3.model.Address.AddressUseEnumFactory; import org.hl7.fhir.dstu3.model.AllergyIntolerance; @@ -77,7 +76,6 @@ import org.hl7.fhir.dstu3.model.Location; import org.hl7.fhir.dstu3.model.Medication; import org.hl7.fhir.dstu3.model.MedicationOrder; import org.hl7.fhir.dstu3.model.MedicationStatement; -import org.hl7.fhir.dstu3.model.MessageHeader.MessageSourceComponent; import org.hl7.fhir.dstu3.model.Observation; import org.hl7.fhir.dstu3.model.Observation.ObservationRelationshipType; import org.hl7.fhir.dstu3.model.Observation.ObservationStatus; @@ -107,6 +105,7 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.api.annotation.Child; import ca.uhn.fhir.model.api.annotation.ResourceDef; import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator; +import ca.uhn.fhir.parser.FooMessageHeaderWithExplicitField.FooMessageSourceComponent; import ca.uhn.fhir.parser.IParserErrorHandler.IParseLocation; import ca.uhn.fhir.rest.client.IGenericClient; import ca.uhn.fhir.rest.server.Constants; @@ -1407,6 +1406,8 @@ public class XmlParserDstu3Test { FooMessageHeader header = new FooMessageHeader(); header.setSource(source); + header.addDestination().setName("DEST"); + Bundle bundle = new Bundle(); bundle.addEntry().setResource(header); @@ -1417,6 +1418,31 @@ public class XmlParserDstu3Test { ourLog.info(encode); assertThat(encode, containsString("")); + assertThat(encode, stringContainsInOrder("")); + assertThat(encode, stringContainsInOrder(" + + When declaring a child with + order=Child.REPLACE_PARENT]]> + the serialized form still put the element at the + end of the resource instead of in the correct + order +