Correctly encode value[x] field names when the datatype is a profiled type such as markdown

This commit is contained in:
jamesagnew 2015-12-14 21:04:27 -05:00
parent 96c0267fe1
commit d95bd269c0
5 changed files with 89 additions and 44 deletions

View File

@ -109,22 +109,26 @@ public class RuntimeChildChoiceDefinition extends BaseRuntimeDeclaredChildDefini
} else { } else {
nextDef = theClassToElementDefinitions.get(next); nextDef = theClassToElementDefinitions.get(next);
BaseRuntimeElementDefinition<?> nextDefForChoice = nextDef; BaseRuntimeElementDefinition<?> nextDefForChoice = nextDef;
if (nextDef instanceof IRuntimeDatatypeDefinition) {
IRuntimeDatatypeDefinition nextDefDatatype = (IRuntimeDatatypeDefinition) nextDef;
if (nextDefDatatype.getProfileOf() != null) {
/* /*
* In HAPI 1.3 the following applied:
* Elements which are called foo[x] and have a choice which is a profiled datatype must use the * Elements which are called foo[x] and have a choice which is a profiled datatype must use the
* unprofiled datatype as the element name. E.g. if foo[x] allows markdown as a datatype, it calls the * unprofiled datatype as the element name. E.g. if foo[x] allows markdown as a datatype, it calls the
* element fooString when encoded, because markdown is a profile of string. This is according to the * element fooString when encoded, because markdown is a profile of string. This is according to the
* FHIR spec * FHIR spec
*
* As of HAPI 1.4 this has been disabled after conversation with Grahame. It appears
* that it is not correct behaviour.
*/ */
nextDefForChoice = null; // if (nextDef instanceof IRuntimeDatatypeDefinition) {
nonPreferred = true; // IRuntimeDatatypeDefinition nextDefDatatype = (IRuntimeDatatypeDefinition) nextDef;
Class<? extends IBaseDatatype> profileType = nextDefDatatype.getProfileOf(); // if (nextDefDatatype.getProfileOf() != null) {
BaseRuntimeElementDefinition<?> elementDef = theClassToElementDefinitions.get(profileType); // nextDefForChoice = null;
elementName = getElementName() + StringUtils.capitalize(elementDef.getName()); // nonPreferred = true;
} // Class<? extends IBaseDatatype> profileType = nextDefDatatype.getProfileOf();
} // BaseRuntimeElementDefinition<?> elementDef = theClassToElementDefinitions.get(profileType);
// elementName = getElementName() + StringUtils.capitalize(elementDef.getName());
// }
// }
if (nextDefForChoice != null) { if (nextDefForChoice != null) {
elementName = getElementName() + StringUtils.capitalize(nextDefForChoice.getName()); elementName = getElementName() + StringUtils.capitalize(nextDefForChoice.getName());
} }

View File

@ -20,9 +20,6 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import net.sf.json.JSON;
import net.sf.json.JSONSerializer;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.hamcrest.core.IsNot; import org.hamcrest.core.IsNot;
import org.hamcrest.core.StringContains; import org.hamcrest.core.StringContains;
@ -30,7 +27,6 @@ import org.hamcrest.text.StringContainsInOrder;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.junit.Before; import org.junit.Before;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.ConfigurationException;
@ -68,6 +64,7 @@ import ca.uhn.fhir.model.dstu.resource.ValueSet.DefineConcept;
import ca.uhn.fhir.model.dstu.valueset.AddressUseEnum; import ca.uhn.fhir.model.dstu.valueset.AddressUseEnum;
import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum; import ca.uhn.fhir.model.dstu.valueset.IdentifierUseEnum;
import ca.uhn.fhir.model.dstu.valueset.NarrativeStatusEnum; import ca.uhn.fhir.model.dstu.valueset.NarrativeStatusEnum;
import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.DateDt; import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt; import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.DecimalDt; import ca.uhn.fhir.model.primitive.DecimalDt;
@ -76,6 +73,8 @@ import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.XhtmlDt; import ca.uhn.fhir.model.primitive.XhtmlDt;
import ca.uhn.fhir.narrative.INarrativeGenerator; import ca.uhn.fhir.narrative.INarrativeGenerator;
import net.sf.json.JSON;
import net.sf.json.JSONSerializer;
public class JsonParserTest { public class JsonParserTest {
private static FhirContext ourCtx; private static FhirContext ourCtx;
@ -1323,6 +1322,7 @@ public class JsonParserTest {
List<ExtensionDt> undeclaredExtensions = obs.getContact().get(0).getName().getFamily().get(0).getUndeclaredExtensions(); List<ExtensionDt> undeclaredExtensions = obs.getContact().get(0).getName().getFamily().get(0).getUndeclaredExtensions();
ExtensionDt undeclaredExtension = undeclaredExtensions.get(0); ExtensionDt undeclaredExtension = undeclaredExtensions.get(0);
assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl()); assertEquals("http://hl7.org/fhir/Profile/iso-21090#qualifier", undeclaredExtension.getUrl());
assertEquals("VV", ((CodeDt)undeclaredExtension.getValue()).getValue());
ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToWriter(obs, new OutputStreamWriter(System.out)); ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToWriter(obs, new OutputStreamWriter(System.out));

View File

@ -142,7 +142,6 @@ public class XmlParserDstu21Test {
ourCtx.newJsonParser().parseResource(encoded); ourCtx.newJsonParser().parseResource(encoded);
} }
@Test @Test
public void testEncodeDoesntIncludeUuidId() { public void testEncodeDoesntIncludeUuidId() {
Patient p = new Patient(); Patient p = new Patient();
@ -153,7 +152,6 @@ public class XmlParserDstu21Test {
assertThat(actual, not(containsString("78ef6f64c2f2"))); assertThat(actual, not(containsString("78ef6f64c2f2")));
} }
@Test @Test
public void testContainedResourceInExtensionUndeclared() { public void testContainedResourceInExtensionUndeclared() {
Patient p = new Patient(); Patient p = new Patient();
@ -341,11 +339,9 @@ public class XmlParserDstu21Test {
String enc = ourCtx.newXmlParser().encodeResourceToString(patient); String enc = ourCtx.newXmlParser().encodeResourceToString(patient);
assertThat(enc, containsString("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://example.com/extensions#someext\"><valueDateTime value=\"2011-01-02T11:13:15\"/></extension>")); assertThat(enc, containsString("<Patient xmlns=\"http://hl7.org/fhir\"><extension url=\"http://example.com/extensions#someext\"><valueDateTime value=\"2011-01-02T11:13:15\"/></extension>"));
assertThat(enc, containsString("<modifierExtension url=\"http://example.com/extensions#modext\"><valueDate value=\"1995-01-02\"/></modifierExtension>")); assertThat(enc, containsString("<modifierExtension url=\"http://example.com/extensions#modext\"><valueDate value=\"1995-01-02\"/></modifierExtension>"));
assertThat(enc, containsString( assertThat(enc, containsString("<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value2\"/></extension></extension>"));
"<extension url=\"http://example.com#parent\"><extension url=\"http://example.com#child\"><valueString value=\"value1\"/></extension><extension url=\"http://example.com#child\"><valueString value=\"value2\"/></extension></extension>"));
assertThat(enc, containsString("<given value=\"Joe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"given\"/></extension></given>")); assertThat(enc, containsString("<given value=\"Joe\"><extension url=\"http://examples.com#givenext\"><valueString value=\"given\"/></extension></given>"));
assertThat(enc, containsString( assertThat(enc, containsString("<given value=\"Shmoe\"><extension url=\"http://examples.com#givenext_parent\"><extension url=\"http://examples.com#givenext_child\"><valueString value=\"CHILD\"/></extension></extension></given>"));
"<given value=\"Shmoe\"><extension url=\"http://examples.com#givenext_parent\"><extension url=\"http://examples.com#givenext_child\"><valueString value=\"CHILD\"/></extension></extension></given>"));
/* /*
* Now parse this back * Now parse this back
@ -541,7 +537,8 @@ public class XmlParserDstu21Test {
/** /**
* See #216 - Profiled datatypes should use their unprofiled parent type as the choice[x] name * See #216 - Profiled datatypes should use their unprofiled parent type as the choice[x] name
*/ */
@Test @Ignore @Test
@Ignore
public void testEncodeAndParseProfiledDatatypeChoice() throws Exception { public void testEncodeAndParseProfiledDatatypeChoice() throws Exception {
IParser xmlParser = ourCtx.newXmlParser(); IParser xmlParser = ourCtx.newXmlParser();
@ -751,10 +748,8 @@ public class XmlParserDstu21Test {
ourLog.info(encoded); ourLog.info(encoded);
// @formatter:on // @formatter:on
assertThat(encoded, assertThat(encoded, stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"123\"/>", "<code>", "<coding>", "<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>",
stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"123\"/>", "<code>", "<coding>", "</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#123\"/>", "<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
"<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>", "</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#123\"/>",
"<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
//@formatter:off //@formatter:off
} }
@ -786,10 +781,8 @@ public class XmlParserDstu21Test {
ourLog.info(encoded); ourLog.info(encoded);
//@formatter:on //@formatter:on
assertThat(encoded, assertThat(encoded, stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"1\"/>", "<code>", "<coding>", "<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>",
stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"1\"/>", "<code>", "<coding>", "</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#1\"/>", "<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
"<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>", "</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#1\"/>",
"<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
//@formatter:off //@formatter:off
} }
@ -824,10 +817,8 @@ public class XmlParserDstu21Test {
ourLog.info(encoded); ourLog.info(encoded);
//@formatter:on //@formatter:on
assertThat(encoded, assertThat(encoded, stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"123\"/>", "<code>", "<coding>", "<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>",
stringContainsInOrder("<MedicationOrder xmlns=\"http://hl7.org/fhir\">", "<contained>", "<Medication xmlns=\"http://hl7.org/fhir\">", "<id value=\"123\"/>", "<code>", "<coding>", "</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#123\"/>", "<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
"<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>", "</Medication>", "</contained>", "<medicationReference>", "<reference value=\"#123\"/>",
"<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationOrder>"));
//@formatter:off //@formatter:off
} }
@ -1630,7 +1621,8 @@ public class XmlParserDstu21Test {
/** /**
* See #191 * See #191
*/ */
@Test @Ignore @Test
@Ignore
public void testParseBundleWithLinksOfUnknownRelation() throws Exception { public void testParseBundleWithLinksOfUnknownRelation() throws Exception {
String input = IOUtils.toString(XmlParserDstu21Test.class.getResourceAsStream("/bundle_orion.xml")); String input = IOUtils.toString(XmlParserDstu21Test.class.getResourceAsStream("/bundle_orion.xml"));
ca.uhn.fhir.model.dstu21.resource.Bundle parsed = ourCtx.newXmlParser().parseResource(ca.uhn.fhir.model.dstu21.resource.Bundle.class, input); ca.uhn.fhir.model.dstu21.resource.Bundle parsed = ourCtx.newXmlParser().parseResource(ca.uhn.fhir.model.dstu21.resource.Bundle.class, input);
@ -1664,7 +1656,8 @@ public class XmlParserDstu21Test {
/** /**
* see #144 and #146 * see #144 and #146
*/ */
@Test @Ignore @Test
@Ignore
public void testParseContained() { public void testParseContained() {
FhirContext c = FhirContext.forDstu2(); FhirContext c = FhirContext.forDstu2();

View File

@ -68,6 +68,7 @@ import ca.uhn.fhir.model.dstu2.resource.MedicationOrder;
import ca.uhn.fhir.model.dstu2.resource.MedicationStatement; import ca.uhn.fhir.model.dstu2.resource.MedicationStatement;
import ca.uhn.fhir.model.dstu2.resource.Observation; import ca.uhn.fhir.model.dstu2.resource.Observation;
import ca.uhn.fhir.model.dstu2.resource.Organization; import ca.uhn.fhir.model.dstu2.resource.Organization;
import ca.uhn.fhir.model.dstu2.resource.Parameters;
import ca.uhn.fhir.model.dstu2.resource.Patient; import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.dstu2.valueset.AddressUseEnum; import ca.uhn.fhir.model.dstu2.valueset.AddressUseEnum;
import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum; import ca.uhn.fhir.model.dstu2.valueset.AdministrativeGenderEnum;
@ -84,6 +85,7 @@ import ca.uhn.fhir.model.primitive.DateDt;
import ca.uhn.fhir.model.primitive.DateTimeDt; import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.MarkdownDt;
import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.parser.IParserErrorHandler.IParseLocation; import ca.uhn.fhir.parser.IParserErrorHandler.IParseLocation;
import ca.uhn.fhir.rest.client.IGenericClient; import ca.uhn.fhir.rest.client.IGenericClient;
@ -93,6 +95,46 @@ public class XmlParserDstu2Test {
private static final FhirContext ourCtx = FhirContext.forDstu2(); private static final FhirContext ourCtx = FhirContext.forDstu2();
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserDstu2Test.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlParserDstu2Test.class);
@Test
public void testChoiceTypeWithProfiledType() {
//@formatter:off
String input = "<Patient xmlns=\"http://hl7.org/fhir\">\n" +
" <extension url=\"http://example.com\">\n" +
" <valueMarkdown value=\"THIS IS MARKDOWN\"/>\n" +
" </extension>\n" +
"</Patient>";
//@formatter:on
Patient parsed = ourCtx.newXmlParser().parseResource(Patient.class, input);
assertEquals(1, parsed.getUndeclaredExtensions().size());
ExtensionDt ext = parsed.getUndeclaredExtensions().get(0);
assertEquals("http://example.com", ext.getUrl());
assertEquals("THIS IS MARKDOWN", ((MarkdownDt)ext.getValue()).getValue());
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(parsed);
assertThat(encoded, containsString("<valueMarkdown value=\"THIS IS MARKDOWN\"/>"));
}
@Test
public void testChoiceTypeWithProfiledType2() {
Parameters par = new Parameters();
par.addParameter().setValue((StringDt)new StringDt().setValue("ST"));
par.addParameter().setValue((MarkdownDt)new MarkdownDt().setValue("MD"));
String str = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(par);
ourLog.info(str);
assertThat(str, stringContainsInOrder("<valueString value=\"ST\"/>", "<valueMarkdown value=\"MD\"/>"));
par = ourCtx.newXmlParser().parseResource(Parameters.class, str);
assertEquals(2, par.getParameter().size());
assertEquals(StringDt.class, par.getParameter().get(0).getValue().getClass());
assertEquals(MarkdownDt.class, par.getParameter().get(1).getValue().getClass());
}
@Test @Test
public void testBundleWithBinary() { public void testBundleWithBinary() {
//@formatter:off //@formatter:off

View File

@ -65,6 +65,12 @@
remains committed to supporting JDK 6+ in the compiled library, but these remains committed to supporting JDK 6+ in the compiled library, but these
days it can only be built using JDK 8. Thanks to joelsch for the PR! days it can only be built using JDK 8. Thanks to joelsch for the PR!
</action> </action>
<action type="fix">
When serializing a value[x] field, if the value type was a profiled type (e.g. markdown is a
profile of string) HAPI 1.3 would use the base type in the element name, e.g.
valueString instead of valueMarkdown. After discussion with Grahame, this appears to
be incorrect behaviour so it has been fixed.
</action>
</release> </release>
<release version="1.3" date="2015-11-14"> <release version="1.3" date="2015-11-14">
<action type="add"> <action type="add">