Fixed #622 Extension lost on ID datatype or extension of type primitive during parsing

This commit is contained in:
Sebastien Riviere 2017-07-24 13:43:55 +02:00
parent f5f1f5bd67
commit 0fd5a44b5e
8 changed files with 522 additions and 277 deletions

View File

@ -385,7 +385,7 @@ public class IdDt extends UriDt implements /*IPrimitiveDatatype<String>, */IIdTy
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
return isBlank(getValue()); return super.isBaseEmpty() && isBlank(getValue());
} }
@Override @Override

View File

@ -95,6 +95,8 @@ import ca.uhn.fhir.parser.json.JsonLikeValue.ValueType;
import ca.uhn.fhir.parser.json.JsonLikeWriter; import ca.uhn.fhir.parser.json.JsonLikeWriter;
import ca.uhn.fhir.rest.server.EncodingEnum; import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.util.ElementUtil; import ca.uhn.fhir.util.ElementUtil;
import static ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum.ID_DATATYPE;
import static ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum.PRIMITIVE_DATATYPE;
/** /**
* This class is the FHIR JSON parser/encoder. Users should not interact with this class directly, but should use * This class is the FHIR JSON parser/encoder. Users should not interact with this class directly, but should use
@ -867,14 +869,28 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
} }
write(theEventWriter, "resourceType", resDef.getName()); write(theEventWriter, "resourceType", resDef.getName());
if (theResourceId != null && theResourceId.hasIdPart()) { if (theResourceId != null && theResourceId.hasIdPart()) {
write(theEventWriter, "id", theResourceId.getIdPart()); write(theEventWriter, "id", theResourceId.getIdPart());
if (theResourceId.hasFormatComment()) { final List<HeldExtension> extensions = new ArrayList<HeldExtension>(0);
beginObject(theEventWriter, "_id"); final List<HeldExtension> modifierExtensions = new ArrayList<HeldExtension>(0);
writeCommentsPreAndPost(theResourceId, theEventWriter); // Undeclared extensions
theEventWriter.endObject(); extractUndeclaredExtensions(theResourceId, extensions, modifierExtensions, null, null);
} boolean haveExtension = false;
} if (!extensions.isEmpty()) {
haveExtension = true;
}
if (theResourceId.hasFormatComment() || haveExtension) {
beginObject(theEventWriter, "_id");
if (theResourceId.hasFormatComment()) {
writeCommentsPreAndPost(theResourceId, theEventWriter);
}
if (haveExtension) {
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions);
}
theEventWriter.endObject();
}
}
if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1) && theResource instanceof IResource) { if (myContext.getVersion().getVersion().isNewerThan(FhirVersionEnum.DSTU1) && theResource instanceof IResource) {
IResource resource = (IResource) theResource; IResource resource = (IResource) theResource;
@ -1428,41 +1444,78 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
} }
} }
private void parseExtension(ParserState<?> theState, JsonLikeArray theValues, boolean theIsModifier) { private void parseExtension(ParserState<?> theState, JsonLikeArray theValues, boolean theIsModifier) {
for (int i = 0; i < theValues.size(); i++) { int allUnderscoreNames = 0;
JsonLikeObject nextExtObj = JsonLikeValue.asObject(theValues.get(i)); int handledUnderscoreNames = 0;
JsonLikeValue jsonElement = nextExtObj.get("url");
String url; for (int i = 0; i < theValues.size(); i++) {
if (null == jsonElement || !(jsonElement.isScalar())) { JsonLikeObject nextExtObj = JsonLikeValue.asObject(theValues.get(i));
String parentElementName; JsonLikeValue jsonElement = nextExtObj.get("url");
if (theIsModifier) { String url;
parentElementName = "modifierExtension"; if (null == jsonElement || !(jsonElement.isScalar())) {
} else { String parentElementName;
parentElementName = "extension"; if (theIsModifier) {
} parentElementName = "modifierExtension";
getErrorHandler().missingRequiredElement(new ParseLocation(parentElementName), "url"); } else {
url = null; parentElementName = "extension";
} else { }
url = getExtensionUrl(jsonElement.getAsString()); getErrorHandler().missingRequiredElement(new ParseLocation(parentElementName), "url");
} url = null;
theState.enteringNewElementExtension(null, url, theIsModifier, getServerBaseUrl()); } else {
for (String next : nextExtObj.keySet()) { url = getExtensionUrl(jsonElement.getAsString());
if ("url".equals(next)) { }
continue; theState.enteringNewElementExtension(null, url, theIsModifier, getServerBaseUrl());
} else if ("extension".equals(next)) { for (String next : nextExtObj.keySet()) {
JsonLikeArray jsonVal = JsonLikeValue.asArray(nextExtObj.get(next)); if ("url".equals(next)) {
parseExtension(theState, jsonVal, false); continue;
} else if ("modifierExtension".equals(next)) { } else if ("extension".equals(next)) {
JsonLikeArray jsonVal = JsonLikeValue.asArray(nextExtObj.get(next)); JsonLikeArray jsonVal = JsonLikeValue.asArray(nextExtObj.get(next));
parseExtension(theState, jsonVal, true); parseExtension(theState, jsonVal, false);
} else { } else if ("modifierExtension".equals(next)) {
JsonLikeValue jsonVal = nextExtObj.get(next); JsonLikeArray jsonVal = JsonLikeValue.asArray(nextExtObj.get(next));
parseChildren(theState, next, jsonVal, null, null, false); parseExtension(theState, jsonVal, true);
} } else if (next.charAt(0) == '_') {
} allUnderscoreNames++;
theState.endingElement(); continue;
} } else {
} JsonLikeValue jsonVal = nextExtObj.get(next);
String alternateName = '_' + next;
JsonLikeValue alternateVal = nextExtObj.get(alternateName);
if (alternateVal != null) {
handledUnderscoreNames++;
}
parseChildren(theState, next, jsonVal, alternateVal, alternateName, false);
}
}
/*
* This happens if an element has an extension but no actual value. I.e.
* if a resource has a "_status" element but no corresponding "status"
* element. This could be used to handle a null value with an extension
* for example.
*/
if (allUnderscoreNames > handledUnderscoreNames) {
for (String alternateName : nextExtObj.keySet()) {
if (alternateName.startsWith("_") && alternateName.length() > 1) {
JsonLikeValue nextValue = nextExtObj.get(alternateName);
if (nextValue != null) {
if (nextValue.isObject()) {
String nextName = alternateName.substring(1);
if (nextExtObj.get(nextName) == null) {
theState.enteringNewElement(null, nextName);
parseAlternates(nextValue, theState, alternateName, alternateName);
theState.endingElement();
}
} else {
getErrorHandler().incorrectJsonType(null, alternateName, ValueType.OBJECT, null, nextValue.getJsonType(), null);
}
}
}
}
}
theState.endingElement();
}
}
private void parseFhirComments(JsonLikeValue theObject, ParserState<?> theState) { private void parseFhirComments(JsonLikeValue theObject, ParserState<?> theState) {
if (theObject.isArray()) { if (theObject.isArray()) {
@ -1842,6 +1895,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
} else { } else {
String childName = myDef.getChildNameByDatatype(myValue.getClass()); String childName = myDef.getChildNameByDatatype(myValue.getClass());
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName, false, myParent, false); encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName, false, myParent, false);
managePrimitiveExtension(myValue, theResDef, theResource, theEventWriter, def, childName);
} }
theEventWriter.endObject(); theEventWriter.endObject();
@ -1897,13 +1951,34 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
throw new ConfigurationException("Unable to encode extension, unregognized child element type: " + value.getClass().getCanonicalName()); throw new ConfigurationException("Unable to encode extension, unregognized child element type: " + value.getClass().getCanonicalName());
} }
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName, true, myParent, false); encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName, true, myParent, false);
managePrimitiveExtension(value, theResDef, theResource, theEventWriter, childDef, childName);
} }
// theEventWriter.name(myUndeclaredExtension.get); // theEventWriter.name(myUndeclaredExtension.get);
theEventWriter.endObject(); theEventWriter.endObject();
} }
} private void managePrimitiveExtension(final IBase theValue, final RuntimeResourceDefinition theResDef, final IBaseResource theResource, final JsonLikeWriter theEventWriter, final BaseRuntimeElementDefinition<?> def, final String childName) throws IOException {
if (def.getChildType().equals(ID_DATATYPE) || def.getChildType().equals(PRIMITIVE_DATATYPE)) {
final List<HeldExtension> extensions = new ArrayList<HeldExtension>(0);
final List<HeldExtension> modifierExtensions = new ArrayList<HeldExtension>(0);
// Undeclared extensions
extractUndeclaredExtensions(theValue, extensions, modifierExtensions, myParent, null);
// Declared extensions
if (def != null) {
extractDeclaredExtensions(theValue, def, extensions, modifierExtensions, myParent);
}
boolean haveContent = false;
if (!extensions.isEmpty() || !modifierExtensions.isEmpty()) {
haveContent = true;
}
if (haveContent) {
beginObject(theEventWriter, '_' + childName);
writeExtensionsAsDirectChild(theResource, theEventWriter, theResDef, extensions, modifierExtensions);
theEventWriter.endObject();
}
}
}
}
} }

View File

@ -1473,6 +1473,7 @@ class ParserState<T> {
push(newState); push(newState);
return; return;
} }
case ID_DATATYPE:
case PRIMITIVE_DATATYPE: { case PRIMITIVE_DATATYPE: {
RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target; RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target;
IPrimitiveType<?> newChildInstance = primitiveTarget.newInstance(myDefinition.getInstanceConstructorArguments()); IPrimitiveType<?> newChildInstance = primitiveTarget.newInstance(myDefinition.getInstanceConstructorArguments());
@ -2261,13 +2262,19 @@ class ParserState<T> {
String resourceName = myContext.getResourceDefinition(nextResource).getName(); String resourceName = myContext.getResourceDefinition(nextResource).getName();
String bundleIdPart = nextResource.getId().getIdPart(); String bundleIdPart = nextResource.getId().getIdPart();
if (isNotBlank(bundleIdPart)) { if (isNotBlank(bundleIdPart)) {
// if (isNotBlank(entryBaseUrl)) { // if (isNotBlank(entryBaseUrl)) {
// nextResource.setId(new IdDt(entryBaseUrl, resourceName, bundleIdPart, version)); // nextResource.setId(new IdDt(entryBaseUrl, resourceName, bundleIdPart, version));
// } else { // } else {
nextResource.setId(new IdDt(null, resourceName, bundleIdPart, version)); IdDt previousId = nextResource.getId();
// } nextResource.setId(new IdDt(null, resourceName, bundleIdPart, version));
// Copy extensions
if (!previousId.getAllUndeclaredExtensions().isEmpty()) {
for (final ExtensionDt ext : previousId.getAllUndeclaredExtensions()) {
nextResource.getId().addUndeclaredExtension(ext);
}
}
// }
} }
} }
} }

View File

@ -507,13 +507,17 @@ public class XmlParser extends BaseParser /*implements IParser */{
switch (childDef.getChildType()) { switch (childDef.getChildType()) {
case ID_DATATYPE: { case ID_DATATYPE: {
IIdType value = IIdType.class.cast(theElement); IIdType value = IIdType.class.cast(theElement);
String encodedValue = "id".equals(childName) ? value.getIdPart() : value.getValue(); String encodedValue = "id".equals(childName) ? value.getIdPart() : value.getValue();
theEventWriter.writeStartElement(childName); if (StringUtils.isNotBlank(encodedValue) || super.hasExtensions(value)) {
theEventWriter.writeAttribute("value", encodedValue); theEventWriter.writeStartElement(childName);
encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource); if (StringUtils.isNotBlank(encodedValue)) {
theEventWriter.writeEndElement(); theEventWriter.writeAttribute("value", encodedValue);
break; }
encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource);
theEventWriter.writeEndElement();
}
break;
} }
case PRIMITIVE_DATATYPE: { case PRIMITIVE_DATATYPE: {
IPrimitiveType<?> pd = IPrimitiveType.class.cast(theElement); IPrimitiveType<?> pd = IPrimitiveType.class.cast(theElement);
@ -756,13 +760,15 @@ public class XmlParser extends BaseParser /*implements IParser */{
theEventWriter.writeDefaultNamespace(FHIR_NS); theEventWriter.writeDefaultNamespace(FHIR_NS);
if (theResource instanceof IAnyResource) { if (theResource instanceof IAnyResource) {
// HL7.org Structures // HL7.org Structures
if (theResourceId != null) { if (theResourceId != null) {
writeCommentsPre(theEventWriter, theResourceId); writeCommentsPre(theEventWriter, theResourceId);
writeOptionalTagWithValue(theEventWriter, "id", theResourceId.getIdPart()); theEventWriter.writeStartElement("id");
writeCommentsPost(theEventWriter, theResourceId); theEventWriter.writeAttribute("value", theResourceId.getIdPart());
} encodeExtensionsIfPresent(theResource, theEventWriter, theResourceId, false);
theEventWriter.writeEndElement();
writeCommentsPost(theEventWriter, theResourceId);
}
encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, theContainedResource, new CompositeChildElement(resDef)); encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, theContainedResource, new CompositeChildElement(resDef));
@ -773,11 +779,16 @@ public class XmlParser extends BaseParser /*implements IParser */{
// DSTU2+ // DSTU2+
IResource resource = (IResource) theResource; IResource resource = (IResource) theResource;
if (theResourceId != null) { if (theResourceId != null) {
writeCommentsPre(theEventWriter, theResourceId); /* writeCommentsPre(theEventWriter, theResourceId);
writeOptionalTagWithValue(theEventWriter, "id", theResourceId.getIdPart()); writeOptionalTagWithValue(theEventWriter, "id", theResourceId.getIdPart());
writeCommentsPost(theEventWriter, theResourceId); writeCommentsPost(theEventWriter, theResourceId);*/
} theEventWriter.writeStartElement("id");
theEventWriter.writeAttribute("value", theResourceId.getIdPart());
encodeExtensionsIfPresent(theResource, theEventWriter, theResourceId, false);
theEventWriter.writeEndElement();
writeCommentsPost(theEventWriter, theResourceId);
}
InstantDt updated = (InstantDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED); InstantDt updated = (InstantDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
IdDt resourceId = resource.getId(); IdDt resourceId = resource.getId();

View File

@ -1,121 +1,206 @@
package ca.uhn.fhir.parser; package ca.uhn.fhir.parser;
import static org.junit.Assert.assertEquals;
import org.junit.AfterClass;
import org.junit.Ignore;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt; import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.TestUtil;
import org.junit.AfterClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/** /**
* Created by Sébastien Rivière 12/04/2017 * Created by Sébastien Rivière 12/04/2017
*/ */
public class ElementWithExtensionDstu2Test { public class ElementWithExtensionDstu2Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ca.uhn.fhir.parser.ElementWithExtensionDstu2Test.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ca.uhn.fhir.parser.ElementWithExtensionDstu2Test.class);
private static FhirContext ctx = FhirContext.forDstu2(); private final FhirContext ctx = FhirContext.forDstu2();
@AfterClass @AfterClass
public static void afterClassClearContext() { public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest(); TestUtil.clearAllStaticFieldsForUnitTest();
} }
@Test @Test
@Ignore public void testExtensionOnPrimitiveExtensionJson() throws Exception {
public void testExtensionOnPrimitiveExtensionJson() throws Exception { MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); patient.setId("1");
patient.setId("1"); final HumanNameDt name = patient.getNameFirstRep();
patient.getPetName().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK")); name.addFamily(new StringDt("family"));
final IParser parser = ctx.newJsonParser().setPrettyPrint(true); name.getFamilyFirstRep().addUndeclaredExtension(new ExtensionDt(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK")));
parser.setServerBaseUrl("http://foo");
final String json = parser.encodeResourceToString(patient);
ourLog.info(json); final StringDt stringExt = new StringDt();
stringExt.setValue("myStringExt");
stringExt.addUndeclaredExtension(new ExtensionDt(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK")));
final ExtensionDt ext = new ExtensionDt();
ext.setValue(stringExt);
ext.setUrl("/myExt");
patient.addUndeclaredExtension(ext);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
assertEquals(1, patient.getPetName().getUndeclaredExtensions().size());
}
@Test patient.setPetName(new StringDt("myPet"));
public void testExtensionOnPrimitiveExtensionXml() throws Exception { patient.getPetName().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.getPetName().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
parser.setServerBaseUrl("http://foo");
final String xml = parser.encodeResourceToString(patient);
ourLog.info(xml); final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
final String json = parser.encodeResourceToString(patient);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml); ourLog.info(json);
assertEquals(1, patient.getPetName().getUndeclaredExtensions().size());
}
@Test patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
@Ignore assertEquals(1, patient.getName().get(0).getFamilyFirstRep().getUndeclaredExtensions().size());
public void testExtensionOnIDDatatypeJson() throws Exception { assertEquals(1, ((StringDt) patient.getUndeclaredExtensionsByUrl("/myExt").get(0).getValue()).getUndeclaredExtensions().size());
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); assertEquals(1, patient.getPetName().getUndeclaredExtensions().size());
patient.setId("1"); }
patient.getId().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
parser.setServerBaseUrl("http://foo");
final String json = parser.encodeResourceToString(patient);
ourLog.info(json); @Test
public void testExtensionOnPrimitiveExtensionWithNullValueJson() throws Exception {
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.getPetName().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
final String json = parser.encodeResourceToString(patient);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json); ourLog.info(json);
assertEquals(1, patient.getId().getUndeclaredExtensions().size());
}
@Test patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
@Ignore assertEquals(1, patient.getPetName().getUndeclaredExtensions().size());
public void testExtensionOnIDDatatypeXml() throws Exception { }
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.getId().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
parser.setServerBaseUrl("http://foo");
final String xml = parser.encodeResourceToString(patient);
ourLog.info(xml);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml); @Test
assertEquals(1, patient.getId().getUndeclaredExtensions().size()); public void testExtensionOnPrimitiveExtensionXml() throws Exception {
} MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
@Test final HumanNameDt name = patient.getNameFirstRep();
@Ignore name.addFamily(new StringDt("family"));
public void testExtensionOnIDDatatypeExtensionJson() throws Exception { name.getFamilyFirstRep().addUndeclaredExtension(new ExtensionDt(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK")));
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.getCustomId().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
parser.setServerBaseUrl("http://foo");
final String json = parser.encodeResourceToString(patient);
ourLog.info(json); final StringDt stringExt = new StringDt();
stringExt.setValue("myStringExt");
stringExt.addUndeclaredExtension(new ExtensionDt(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK")));
final ExtensionDt ext = new ExtensionDt();
ext.setValue(stringExt);
ext.setUrl("/myExt");
patient.addUndeclaredExtension(ext);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
assertEquals(1, patient.getCustomId().getUndeclaredExtensions().size());
}
@Test patient.setPetName(new StringDt("myPet"));
@Ignore patient.getPetName().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
public void testExtensionOnIDDatatypeExtensionXml() throws Exception { final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); final String xml = parser.encodeResourceToString(patient);
patient.setId("1");
patient.getCustomId().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
parser.setServerBaseUrl("http://foo");
final String xml = parser.encodeResourceToString(patient);
ourLog.info(xml); ourLog.info(xml);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml); patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
assertEquals(1, patient.getCustomId().getUndeclaredExtensions().size()); assertEquals(1, patient.getName().get(0).getFamilyFirstRep().getUndeclaredExtensions().size());
} assertEquals(1, ((StringDt) patient.getUndeclaredExtensionsByUrl("/myExt").get(0).getValue()).getUndeclaredExtensions().size());
assertEquals(1, patient.getPetName().getUndeclaredExtensions().size());
}
@Test
public void testExtensionOnPrimitiveExtensionWithNullValueXml() throws Exception {
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.getPetName().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
final String xml = parser.encodeResourceToString(patient);
ourLog.info(xml);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
assertEquals(1, patient.getPetName().getUndeclaredExtensions().size());
}
@Test
public void testExtensionOnIDDatatypeJson() throws Exception {
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.getId().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
final String json = parser.encodeResourceToString(patient);
ourLog.info(json);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
assertEquals(1, patient.getId().getUndeclaredExtensions().size());
}
@Test
public void testExtensionOnIDDatatypeXml() throws Exception {
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.getId().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
final String xml = parser.encodeResourceToString(patient);
ourLog.info(xml);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
assertEquals(1, patient.getId().getUndeclaredExtensions().size());
}
@Test
public void testExtensionOnIDDatatypeExtensionJson() throws Exception {
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.setCustomId(new IdDt("3"));
patient.getCustomId().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
final String json = parser.encodeResourceToString(patient);
ourLog.info(json);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
assertEquals(1, patient.getCustomId().getUndeclaredExtensions().size());
}
@Test
public void testExtensionOnIDDatatypeExtensionNullValueJson() throws Exception {
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.getCustomId().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
final String json = parser.encodeResourceToString(patient);
ourLog.info(json);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
assertEquals(1, patient.getCustomId().getUndeclaredExtensions().size());
}
@Test
public void testExtensionOnIDDatatypeExtensionXml() throws Exception {
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.setCustomId(new IdDt("4"));
patient.getCustomId().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
final String xml = parser.encodeResourceToString(patient);
ourLog.info(xml);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
assertEquals(1, patient.getCustomId().getUndeclaredExtensions().size());
}
@Test
public void testExtensionOnIDDatatypeExtensionNullValueXml() throws Exception {
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.getCustomId().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"));
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
final String xml = parser.encodeResourceToString(patient);
ourLog.info(xml);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
assertEquals(1, patient.getCustomId().getUndeclaredExtensions().size());
}
} }

View File

@ -437,7 +437,7 @@ public final class IdType extends UriType implements IPrimitiveType<String>, IId
@Override @Override
public boolean isEmpty() { public boolean isEmpty() {
return isBlank(getValue()); return super.isEmpty() && isBlank(getValue());
} }
@Override @Override

View File

@ -1,116 +1,183 @@
package ca.uhn.fhir.parser; package ca.uhn.fhir.parser;
import static org.junit.Assert.assertEquals;
import org.hl7.fhir.dstu3.model.StringType;
import org.junit.AfterClass;
import org.junit.Ignore;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.util.TestUtil; import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.dstu3.model.Extension;
import org.hl7.fhir.dstu3.model.HumanName;
import org.hl7.fhir.dstu3.model.IdType;
import org.hl7.fhir.dstu3.model.StringType;
import org.junit.AfterClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/** /**
* Created by Sébastien Rivière 12/04/2017 * Created by Sébastien Rivière 12/04/2017
*/ */
public class ElementWithExtensionDstu3Test { public class ElementWithExtensionDstu3Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ca.uhn.fhir.parser.ElementWithExtensionDstu3Test.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ca.uhn.fhir.parser.ElementWithExtensionDstu3Test.class);
private static final FhirContext ctx = FhirContext.forDstu3(); private final FhirContext ctx = FhirContext.forDstu3();
@AfterClass @AfterClass
public static void afterClassClearContext() { public static void afterClassClearContext() {
TestUtil.clearAllStaticFieldsForUnitTest(); TestUtil.clearAllStaticFieldsForUnitTest();
} }
@Test @Test
@Ignore public void testNullFlavorPrimitiveExtensionJson() throws Exception {
public void testNullFlavorPrimitiveExtensionJson() throws Exception { MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); patient.setId("1");
patient.setId("1"); final HumanName name = patient.getNameFirstRep();
patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK")); name.setFamily("family");
final IParser parser = ctx.newJsonParser().setPrettyPrint(true); name.getFamilyElement().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
final String json = parser.encodeResourceToString(patient);
ourLog.info(json); patient.setPetName(new StringType("myPet"));
patient.getExtensionsByUrl("/petname");
patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json); final StringType stringExt = new StringType();
assertEquals(1, patient.getPetName().getExtension().size()); stringExt.setValue("myStringExt");
} stringExt.addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
final Extension ext = new Extension();
ext.setValue(stringExt);
ext.setUrl("/myExt");
patient.addExtension(ext);
@Test final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
@Ignore final String json = parser.encodeResourceToString(patient);
public void testNullFlavorPrimitiveExtensionXml() throws Exception {
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
final String xml = parser.encodeResourceToString(patient);
ourLog.info(xml); ourLog.info(json);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml); patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
assertEquals(1, patient.getPetName().getExtension().size()); assertEquals(1, patient.getName().get(0).getFamilyElement().getExtension().size());
} assertEquals(1, patient.getExtensionsByUrl("/myExt").get(0).getValue().getExtension().size());
assertEquals(1, patient.getPetName().getExtension().size());
}
@Test @Test
@Ignore public void testNullFlavorPrimitiveExtensionNullValueJson() throws Exception {
public void testNullFlavorIDDatatypeJson() throws Exception { MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); patient.setId("1");
patient.setId("1"); patient.getExtensionsByUrl("/petname");
patient.getIdElement().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK")); patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
final String json = parser.encodeResourceToString(patient);
ourLog.info(json); final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
final String json = parser.encodeResourceToString(patient);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json); ourLog.info(json);
assertEquals(1, patient.getIdElement().getExtension().size());
}
@Test patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
@Ignore assertEquals(1, patient.getPetName().getExtension().size());
public void testNullFlavorIDDatatypeXml() throws Exception { }
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.getIdElement().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
final String xml = parser.encodeResourceToString(patient);
ourLog.info(xml); @Test
public void testNullFlavorPrimitiveExtensionXml() throws Exception {
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
final HumanName name = patient.getNameFirstRep();
name.setFamily("family");
name.getFamilyElement().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml); patient.setPetName(new StringType("myPet"));
assertEquals(1, patient.getIdElement().getExtension().size()); patient.getExtensionsByUrl("/petname");
} patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
@Test final StringType stringExt = new StringType();
@Ignore stringExt.setValue("myStringExt");
public void testNullFlavorExtensionIDDatatypeJson() throws Exception { stringExt.addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); final Extension ext = new Extension();
patient.setId("1"); ext.setValue(stringExt);
patient.getCustomId().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK")); ext.setUrl("/myExt");
final IParser parser = ctx.newJsonParser().setPrettyPrint(true); patient.addExtension(ext);
final String json = parser.encodeResourceToString(patient);
ourLog.info(json); final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
final String xml = parser.encodeResourceToString(patient);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json); ourLog.info(xml);
assertEquals(1, patient.getCustomId().getExtension().size());
}
@Test patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
@Ignore assertEquals(1, patient.getName().get(0).getFamilyElement().getExtension().size());
public void testNullFlavorExtensionIDDatatypeXml() throws Exception { assertEquals(1, patient.getExtensionsByUrl("/myExt").get(0).getValue().getExtension().size());
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); assertEquals(1, patient.getPetName().getExtension().size());
patient.setId("1"); }
patient.getCustomId().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
final String xml = parser.encodeResourceToString(patient);
ourLog.info(xml);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml); @Test
assertEquals(1, patient.getCustomId().getExtension().size()); public void testNullFlavorPrimitiveExtensionNullValueXml() throws Exception {
} MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.getExtensionsByUrl("/petname");
patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
final String xml = parser.encodeResourceToString(patient);
ourLog.info(xml);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
assertEquals(1, patient.getPetName().getExtension().size());
}
@Test
public void testNullFlavorIDDatatypeJson() throws Exception {
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.getIdElement().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
final String json = parser.encodeResourceToString(patient);
ourLog.info(json);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
assertEquals(1, patient.getIdElement().getExtension().size());
}
@Test
public void testNullFlavorIDDatatypeXml() throws Exception {
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.getIdElement().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
final String xml = parser.encodeResourceToString(patient);
ourLog.info(xml);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
assertEquals(1, patient.getIdElement().getExtension().size());
}
@Test
public void testNullFlavorExtensionIDDatatypeJson() throws Exception {
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
patient.setCustomId(new IdType(("4")));
patient.getCustomId().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
final IParser parser = ctx.newJsonParser().setPrettyPrint(true);
final String json = parser.encodeResourceToString(patient);
ourLog.info(json);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json);
assertEquals(1, patient.getCustomId().getExtension().size());
}
@Test
public void testNullFlavorExtensionIDDatatypeXml() throws Exception {
MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension();
patient.setId("1");
final IParser parser = ctx.newXmlParser().setPrettyPrint(true);
patient.setCustomId(new IdType(("4")));
patient.getCustomId().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK"));
final String xml = parser.encodeResourceToString(patient);
ourLog.info(xml);
patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml);
assertEquals(1, patient.getCustomId().getExtension().size());
}
} }

View File

@ -11,42 +11,42 @@ import org.hl7.fhir.dstu3.model.StringType;
@ResourceDef() @ResourceDef()
public class MyPatientWithCustomUrlExtension extends Patient { public class MyPatientWithCustomUrlExtension extends Patient {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Child(name = "petName") @Child(name = "petName")
@Extension(url = "/petname", definedLocally = false, isModifier = false) @Extension(url = "/petname", definedLocally = false, isModifier = false)
@Description(shortDefinition = "The name of the patient's favourite pet") @Description(shortDefinition = "The name of the patient's favourite pet")
private StringType myPetName; private StringType myPetName;
@Child(name = "customid") @Child(name = "customid")
@Extension(url = "/customid", definedLocally = false, isModifier = false) @Extension(url = "/customid", definedLocally = false, isModifier = false)
@Description(shortDefinition = "The customid of the patient's ") @Description(shortDefinition = "The customid of the patient's ")
private IdType myCustomId; private IdType myCustomId;
public StringType getPetName() { public StringType getPetName() {
if (myPetName == null) { if (myPetName == null) {
myPetName = new StringType(); myPetName = new StringType();
}
return myPetName;
} }
return myPetName;
}
public void setPetName(final StringType thePetName) { public void setPetName(final StringType thePetName) {
myPetName = thePetName; myPetName = thePetName;
}
@Override
public boolean isEmpty() {
return super.isEmpty() && myPetName.isEmpty();
}
public IdType getCustomId() {
if (myCustomId == null) {
myCustomId = new IdType();
} }
return myCustomId;
}
public void setCustomId(final IdType myCustomId) { @Override
this.myCustomId = myCustomId; public boolean isEmpty() {
} return super.isEmpty() && getCustomId().isEmpty() && getPetName().isEmpty();
}
public IdType getCustomId() {
if (myCustomId == null) {
myCustomId = new IdType();
}
return myCustomId;
}
public void setCustomId(final IdType myCustomId) {
this.myCustomId = myCustomId;
}
} }