diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/IdDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/IdDt.java index 649eb70307a..ec9a9deb3fb 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/IdDt.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/IdDt.java @@ -386,7 +386,7 @@ public class IdDt extends UriDt implements /*IPrimitiveDatatype, */IIdTy @Override public boolean isEmpty() { - return isBlank(getValue()); + return super.isBaseEmpty() && isBlank(getValue()); } @Override diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java index d20ecb0d793..c28e948c026 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java @@ -47,6 +47,8 @@ import ca.uhn.fhir.parser.json.JsonLikeValue.ScalarType; import ca.uhn.fhir.parser.json.JsonLikeValue.ValueType; import ca.uhn.fhir.rest.api.EncodingEnum; 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 @@ -610,14 +612,28 @@ public class JsonParser extends BaseParser implements IJsonLikeParser { } write(theEventWriter, "resourceType", resDef.getName()); - if (theResourceId != null && theResourceId.hasIdPart()) { - write(theEventWriter, "id", theResourceId.getIdPart()); - if (theResourceId.hasFormatComment()) { - beginObject(theEventWriter, "_id"); - writeCommentsPreAndPost(theResourceId, theEventWriter); - theEventWriter.endObject(); - } - } + if (theResourceId != null && theResourceId.hasIdPart()) { + write(theEventWriter, "id", theResourceId.getIdPart()); + final List extensions = new ArrayList(0); + final List modifierExtensions = new ArrayList(0); + // Undeclared extensions + 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 (theResource instanceof IResource) { IResource resource = (IResource) theResource; @@ -1013,41 +1029,78 @@ public class JsonParser extends BaseParser implements IJsonLikeParser { } } - private void parseExtension(ParserState theState, JsonLikeArray theValues, boolean theIsModifier) { - for (int i = 0; i < theValues.size(); i++) { - JsonLikeObject nextExtObj = JsonLikeValue.asObject(theValues.get(i)); - JsonLikeValue jsonElement = nextExtObj.get("url"); - String url; - if (null == jsonElement || !(jsonElement.isScalar())) { - String parentElementName; - if (theIsModifier) { - parentElementName = "modifierExtension"; - } else { - parentElementName = "extension"; - } - getErrorHandler().missingRequiredElement(new ParseLocation(parentElementName), "url"); - url = null; - } else { - url = getExtensionUrl(jsonElement.getAsString()); - } - theState.enteringNewElementExtension(null, url, theIsModifier, getServerBaseUrl()); - for (String next : nextExtObj.keySet()) { - if ("url".equals(next)) { - continue; - } else if ("extension".equals(next)) { - JsonLikeArray jsonVal = JsonLikeValue.asArray(nextExtObj.get(next)); - parseExtension(theState, jsonVal, false); - } else if ("modifierExtension".equals(next)) { - JsonLikeArray jsonVal = JsonLikeValue.asArray(nextExtObj.get(next)); - parseExtension(theState, jsonVal, true); - } else { - JsonLikeValue jsonVal = nextExtObj.get(next); - parseChildren(theState, next, jsonVal, null, null, false); - } - } - theState.endingElement(); - } - } + private void parseExtension(ParserState theState, JsonLikeArray theValues, boolean theIsModifier) { + int allUnderscoreNames = 0; + int handledUnderscoreNames = 0; + + for (int i = 0; i < theValues.size(); i++) { + JsonLikeObject nextExtObj = JsonLikeValue.asObject(theValues.get(i)); + JsonLikeValue jsonElement = nextExtObj.get("url"); + String url; + if (null == jsonElement || !(jsonElement.isScalar())) { + String parentElementName; + if (theIsModifier) { + parentElementName = "modifierExtension"; + } else { + parentElementName = "extension"; + } + getErrorHandler().missingRequiredElement(new ParseLocation(parentElementName), "url"); + url = null; + } else { + url = getExtensionUrl(jsonElement.getAsString()); + } + theState.enteringNewElementExtension(null, url, theIsModifier, getServerBaseUrl()); + for (String next : nextExtObj.keySet()) { + if ("url".equals(next)) { + continue; + } else if ("extension".equals(next)) { + JsonLikeArray jsonVal = JsonLikeValue.asArray(nextExtObj.get(next)); + parseExtension(theState, jsonVal, false); + } else if ("modifierExtension".equals(next)) { + JsonLikeArray jsonVal = JsonLikeValue.asArray(nextExtObj.get(next)); + parseExtension(theState, jsonVal, true); + } else if (next.charAt(0) == '_') { + allUnderscoreNames++; + 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) { if (theObject.isArray()) { @@ -1314,6 +1367,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser { } else { String childName = myDef.getChildNameByDatatype(myValue.getClass()); encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName, false, myParent, false); + managePrimitiveExtension(myValue, theResDef, theResource, theEventWriter, def, childName); } theEventWriter.endObject(); @@ -1368,13 +1422,34 @@ public class JsonParser extends BaseParser implements IJsonLikeParser { throw new ConfigurationException("Unable to encode extension, unregognized child element type: " + value.getClass().getCanonicalName()); } encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName, true, myParent, false); + managePrimitiveExtension(value, theResDef, theResource, theEventWriter, childDef, childName); } // theEventWriter.name(myUndeclaredExtension.get); 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 extensions = new ArrayList(0); + final List modifierExtensions = new ArrayList(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(); + } + } + } + } } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java index 7f1b9921eff..ce00a0dcbdd 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java @@ -422,6 +422,7 @@ class ParserState { push(newState); return; } + case ID_DATATYPE: case PRIMITIVE_DATATYPE: { RuntimePrimitiveDatatypeDefinition primitiveTarget = (RuntimePrimitiveDatatypeDefinition) target; IPrimitiveType newChildInstance = primitiveTarget.newInstance(myDefinition.getInstanceConstructorArguments()); @@ -1155,13 +1156,19 @@ class ParserState { String resourceName = myContext.getResourceDefinition(nextResource).getName(); String bundleIdPart = nextResource.getId().getIdPart(); if (isNotBlank(bundleIdPart)) { - // if (isNotBlank(entryBaseUrl)) { - // nextResource.setId(new IdDt(entryBaseUrl, resourceName, bundleIdPart, version)); - // } else { - nextResource.setId(new IdDt(null, resourceName, bundleIdPart, version)); - // } + // if (isNotBlank(entryBaseUrl)) { + // nextResource.setId(new IdDt(entryBaseUrl, resourceName, bundleIdPart, version)); + // } else { + 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); + } + } + // } } - } } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java index 713c28f07e8..63f67be73ad 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java @@ -184,9 +184,9 @@ public class XmlParser extends BaseParser /* implements IParser */ { heldComments.clear(); } parserState.endingElement(); - // if (parserState.isComplete()) { - // return parserState.getObject(); - // } +// if (parserState.isComplete()) { +// return parserState.getObject(); +// } break; } case XMLStreamConstants.CHARACTERS: { @@ -227,13 +227,17 @@ public class XmlParser extends BaseParser /* implements IParser */ { switch (childDef.getChildType()) { case ID_DATATYPE: { - IIdType value = IIdType.class.cast(theElement); - String encodedValue = "id".equals(childName) ? value.getIdPart() : value.getValue(); - theEventWriter.writeStartElement(childName); - theEventWriter.writeAttribute("value", encodedValue); - encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource); - theEventWriter.writeEndElement(); - break; + IIdType value = IIdType.class.cast(theElement); + String encodedValue = "id".equals(childName) ? value.getIdPart() : value.getValue(); + if (StringUtils.isNotBlank(encodedValue) || super.hasExtensions(value)) { + theEventWriter.writeStartElement(childName); + if (StringUtils.isNotBlank(encodedValue)) { + theEventWriter.writeAttribute("value", encodedValue); + } + encodeExtensionsIfPresent(theResource, theEventWriter, theElement, theIncludedResource); + theEventWriter.writeEndElement(); + } + break; } case PRIMITIVE_DATATYPE: { IPrimitiveType pd = IPrimitiveType.class.cast(theElement); @@ -354,8 +358,7 @@ public class XmlParser extends BaseParser /* implements IParser */ { } if (nextChild instanceof RuntimeChildContainedResources) { - encodeChildElementToStreamWriter(theResource, theEventWriter, null, nextChild.getChildNameByDatatype(null), nextChild.getChildElementDefinitionByDatatype(null), null, theContainedResource, - nextChildElem); + encodeChildElementToStreamWriter(theResource, theEventWriter, null, nextChild.getChildNameByDatatype(null), nextChild.getChildElementDefinitionByDatatype(null), null, theContainedResource, nextChildElem); } else { List values = nextChild.getAccessor().getValues(theElement); @@ -398,8 +401,7 @@ public class XmlParser extends BaseParser /* implements IParser */ { } } - private void encodeExtension(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theContainedResource, CompositeChildElement nextChildElem, BaseRuntimeChildDefinition nextChild, - IBase nextValue, String childName, String extensionUrl, BaseRuntimeElementDefinition childDef) + private void encodeExtension(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theContainedResource, CompositeChildElement nextChildElem, BaseRuntimeChildDefinition nextChild, IBase nextValue, String childName, String extensionUrl, BaseRuntimeElementDefinition childDef) throws XMLStreamException { BaseRuntimeDeclaredChildDefinition extDef = (BaseRuntimeDeclaredChildDefinition) nextChild; if (extDef.isModifier()) { @@ -434,8 +436,7 @@ public class XmlParser extends BaseParser /* implements IParser */ { } } - private void encodeResourceToXmlStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theIncludedResource, boolean theSubResource) - throws XMLStreamException, DataFormatException { + private void encodeResourceToXmlStreamWriter(IBaseResource theResource, XMLStreamWriter theEventWriter, boolean theIncludedResource, boolean theSubResource) throws XMLStreamException, DataFormatException { IIdType resourceId = null; if (StringUtils.isNotBlank(theResource.getIdElement().getIdPart())) { @@ -470,13 +471,15 @@ public class XmlParser extends BaseParser /* implements IParser */ { theEventWriter.writeDefaultNamespace(FHIR_NS); if (theResource instanceof IAnyResource) { - // HL7.org Structures - if (theResourceId != null) { - writeCommentsPre(theEventWriter, theResourceId); - writeOptionalTagWithValue(theEventWriter, "id", theResourceId.getIdPart()); - writeCommentsPost(theEventWriter, theResourceId); - } + if (theResourceId != null) { + writeCommentsPre(theEventWriter, theResourceId); + theEventWriter.writeStartElement("id"); + theEventWriter.writeAttribute("value", theResourceId.getIdPart()); + encodeExtensionsIfPresent(theResource, theEventWriter, theResourceId, false); + theEventWriter.writeEndElement(); + writeCommentsPost(theEventWriter, theResourceId); + } encodeCompositeElementToStreamWriter(theResource, theResource, theEventWriter, theContainedResource, new CompositeChildElement(resDef)); @@ -485,11 +488,16 @@ public class XmlParser extends BaseParser /* implements IParser */ { // DSTU2+ IResource resource = (IResource) theResource; - if (theResourceId != null) { - writeCommentsPre(theEventWriter, theResourceId); - writeOptionalTagWithValue(theEventWriter, "id", theResourceId.getIdPart()); - writeCommentsPost(theEventWriter, theResourceId); - } + if (theResourceId != null) { + /* writeCommentsPre(theEventWriter, theResourceId); + writeOptionalTagWithValue(theEventWriter, "id", theResourceId.getIdPart()); + 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); IdDt resourceId = resource.getId(); diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/ElementWithExtensionDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/ElementWithExtensionDstu2Test.java index c596f24d5be..589ec5855c9 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/ElementWithExtensionDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/parser/ElementWithExtensionDstu2Test.java @@ -1,121 +1,206 @@ 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.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.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 */ public class ElementWithExtensionDstu2Test { - private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ca.uhn.fhir.parser.ElementWithExtensionDstu2Test.class); - private static FhirContext ctx = FhirContext.forDstu2(); + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ca.uhn.fhir.parser.ElementWithExtensionDstu2Test.class); + private final FhirContext ctx = FhirContext.forDstu2(); - @AfterClass - public static void afterClassClearContext() { - TestUtil.clearAllStaticFieldsForUnitTest(); - } + @AfterClass + public static void afterClassClearContext() { + TestUtil.clearAllStaticFieldsForUnitTest(); + } - @Test - @Ignore - public void testExtensionOnPrimitiveExtensionJson() 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); - parser.setServerBaseUrl("http://foo"); - final String json = parser.encodeResourceToString(patient); + @Test + public void testExtensionOnPrimitiveExtensionJson() throws Exception { + MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); + patient.setId("1"); + final HumanNameDt name = patient.getNameFirstRep(); + name.addFamily(new StringDt("family")); + name.getFamilyFirstRep().addUndeclaredExtension(new ExtensionDt(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"))); - 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 - public void testExtensionOnPrimitiveExtensionXml() 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); - parser.setServerBaseUrl("http://foo"); - final String xml = parser.encodeResourceToString(patient); + patient.setPetName(new StringDt("myPet")); + patient.getPetName().addUndeclaredExtension(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK")); - ourLog.info(xml); + final IParser parser = ctx.newJsonParser().setPrettyPrint(true); + final String json = parser.encodeResourceToString(patient); - patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml); - assertEquals(1, patient.getPetName().getUndeclaredExtensions().size()); - } + ourLog.info(json); - @Test - @Ignore - 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); - parser.setServerBaseUrl("http://foo"); - final String json = parser.encodeResourceToString(patient); + patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json); + 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()); + } - 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); - assertEquals(1, patient.getId().getUndeclaredExtensions().size()); - } + ourLog.info(json); - @Test - @Ignore - 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); + patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json); + assertEquals(1, patient.getPetName().getUndeclaredExtensions().size()); + } - ourLog.info(xml); - patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml); - assertEquals(1, patient.getId().getUndeclaredExtensions().size()); - } + @Test + public void testExtensionOnPrimitiveExtensionXml() throws Exception { + MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); + patient.setId("1"); - @Test - @Ignore - public void testExtensionOnIDDatatypeExtensionJson() 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); - parser.setServerBaseUrl("http://foo"); - final String json = parser.encodeResourceToString(patient); + final HumanNameDt name = patient.getNameFirstRep(); + name.addFamily(new StringDt("family")); + name.getFamilyFirstRep().addUndeclaredExtension(new ExtensionDt(false, "http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringDt("UNK"))); - 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 - @Ignore - public void testExtensionOnIDDatatypeExtensionXml() 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); - parser.setServerBaseUrl("http://foo"); - final String xml = parser.encodeResourceToString(patient); + patient.setPetName(new StringDt("myPet")); + 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); + ourLog.info(xml); - patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml); - assertEquals(1, patient.getCustomId().getUndeclaredExtensions().size()); - } + patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml); + 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()); + } } diff --git a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/model/IdType.java b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/model/IdType.java index f9eb2e40098..fc05b70cd50 100644 --- a/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/model/IdType.java +++ b/hapi-fhir-structures-dstu3/src/main/java/org/hl7/fhir/dstu3/model/IdType.java @@ -436,7 +436,7 @@ public final class IdType extends UriType implements IPrimitiveType, IId @Override public boolean isEmpty() { - return isBlank(getValue()); + return super.isEmpty() && isBlank(getValue()); } @Override diff --git a/hapi-fhir-structures-dstu3/src/test/java/MinimizeResources.java b/hapi-fhir-structures-dstu3/src/test/java/MinimizeResources.java deleted file mode 100644 index 46967035bc9..00000000000 --- a/hapi-fhir-structures-dstu3/src/test/java/MinimizeResources.java +++ /dev/null @@ -1,60 +0,0 @@ -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Collection; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.hl7.fhir.dstu3.model.Bundle; -import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent; -import org.hl7.fhir.dstu3.model.DomainResource; -import org.hl7.fhir.dstu3.model.Narrative; -import org.hl7.fhir.dstu3.model.Resource; -import org.junit.AfterClass; - -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.util.TestUtil; - -public class MinimizeResources { -private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(MinimizeResources.class); - - private static FhirContext ourCtx = FhirContext.forDstu3(); - - @AfterClass - public static void afterClassClearContext() { - TestUtil.clearAllStaticFieldsForUnitTest(); - } - - public static void main(String[] args) throws Exception { - - - Collection xml = FileUtils.listFiles(new File("../hapi-fhir-validation-resources-dstu3/src/main/resources/org/hl7/fhir/dstu3/model/profile"), new String[] {"xml"}, false); - for (File next : xml) { - ourLog.info("Checking: {}", next.getAbsoluteFile()); - - String inputFile = IOUtils.toString(new FileReader(next)); - Bundle bundle = (Bundle) ourCtx.newXmlParser().parseResource(inputFile); - for (BundleEntryComponent nextEntry : bundle.getEntry()) { - Resource resource; - resource = nextEntry.getResource(); - if (resource instanceof DomainResource) { - ((DomainResource) resource).setText(new Narrative()); - } - } - - - String output = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(bundle); - if (!output.equals(inputFile)) { - ourLog.info("Rewriting {}", next.getAbsolutePath()); - - FileWriter writer = new FileWriter(next, false); - writer.append(output); - writer.close(); - } - } - - } - -} diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/ElementWithExtensionDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/ElementWithExtensionDstu3Test.java index 686db4ced24..368261b9e59 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/ElementWithExtensionDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/ElementWithExtensionDstu3Test.java @@ -1,116 +1,225 @@ 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.util.TestUtil; +import org.hl7.fhir.dstu3.model.*; +import org.junit.AfterClass; +import org.junit.Test; + +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; /** * Created by Sébastien Rivière 12/04/2017 */ public class ElementWithExtensionDstu3Test { - 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 static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ca.uhn.fhir.parser.ElementWithExtensionDstu3Test.class); + private final FhirContext ctx = FhirContext.forDstu3(); - @AfterClass - public static void afterClassClearContext() { - TestUtil.clearAllStaticFieldsForUnitTest(); - } + @AfterClass + public static void afterClassClearContext() { + TestUtil.clearAllStaticFieldsForUnitTest(); + } - @Test - @Ignore - public void testNullFlavorPrimitiveExtensionJson() 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.newJsonParser().setPrettyPrint(true); - final String json = parser.encodeResourceToString(patient); + @Test + public void testNullFlavorPrimitiveExtensionJson() 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")); - 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); - assertEquals(1, patient.getPetName().getExtension().size()); - } + final StringType stringExt = new StringType(); + 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 - @Ignore - 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); + final IParser parser = ctx.newJsonParser().setPrettyPrint(true); + final String json = parser.encodeResourceToString(patient); - ourLog.info(xml); + ourLog.info(json); - patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml); - assertEquals(1, patient.getPetName().getExtension().size()); - } + patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json); + 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 - @Ignore - 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); + @Test + public void testNullFlavorPrimitiveExtensionNullValueJson() 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")); - ourLog.info(json); + final IParser parser = ctx.newJsonParser().setPrettyPrint(true); + final String json = parser.encodeResourceToString(patient); - patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json); - assertEquals(1, patient.getIdElement().getExtension().size()); - } + ourLog.info(json); - @Test - @Ignore - 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); + patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json); + assertEquals(1, patient.getPetName().getExtension().size()); + } - 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); - assertEquals(1, patient.getIdElement().getExtension().size()); - } + patient.setPetName(new StringType("myPet")); + patient.getExtensionsByUrl("/petname"); + patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK")); - @Test - @Ignore - public void testNullFlavorExtensionIDDatatypeJson() throws Exception { - MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); - patient.setId("1"); - 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); + final StringType stringExt = new StringType(); + 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); - ourLog.info(json); + final IParser parser = ctx.newXmlParser().setPrettyPrint(true); + final String xml = parser.encodeResourceToString(patient); - patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json); - assertEquals(1, patient.getCustomId().getExtension().size()); - } + ourLog.info(xml); - @Test - @Ignore - public void testNullFlavorExtensionIDDatatypeXml() throws Exception { - MyPatientWithCustomUrlExtension patient = new MyPatientWithCustomUrlExtension(); - 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); + patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml); + 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()); + } - ourLog.info(xml); - patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml); - assertEquals(1, patient.getCustomId().getExtension().size()); - } + @Test + 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()); + } + + @Test + public void testExtensionOnResourceIdXml(){ + Patient p = new Patient(); + p.setActive(true); + p.getIdElement().setValue("123"); + p.getIdElement().addExtension().setUrl("http://foo").setValue(new StringType("FOO")); + + IParser parser = ctx.newXmlParser(); + String encoded = parser.encodeResourceToString(p); + assertThat(encoded, containsString("http://foo")); + assertThat(encoded, containsString("FOO")); + + p = (Patient) parser.parseResource(encoded); + assertEquals("Patient/123", p.getId()); + Extension ex = p.getIdElement().getExtension().get(0); + assertEquals("http://foo", ex.getUrl()); + assertEquals("FOO", ex.getValueAsPrimitive().getValueAsString()); + + + } + + @Test + public void testExtensionOnResourceIdJson(){ + Patient p = new Patient(); + p.setActive(true); + p.getIdElement().setValue("123"); + p.getIdElement().addExtension().setUrl("http://foo").setValue(new StringType("FOO")); + + IParser parser = ctx.newJsonParser(); + String encoded = parser.encodeResourceToString(p); + assertThat(encoded, containsString("http://foo")); + assertThat(encoded, containsString("FOO")); + + p = (Patient) parser.parseResource(encoded); + assertEquals("Patient/123", p.getId()); + Extension ex = p.getIdElement().getExtension().get(0); + assertEquals("http://foo", ex.getUrl()); + assertEquals("FOO", ex.getValueAsPrimitive().getValueAsString()); + + + } + } diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/MyPatientWithCustomUrlExtension.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/MyPatientWithCustomUrlExtension.java index cca4b7ede6d..f7800e6ef65 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/MyPatientWithCustomUrlExtension.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/parser/MyPatientWithCustomUrlExtension.java @@ -11,42 +11,42 @@ import org.hl7.fhir.dstu3.model.StringType; @ResourceDef() public class MyPatientWithCustomUrlExtension extends Patient { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - @Child(name = "petName") - @Extension(url = "/petname", definedLocally = false, isModifier = false) - @Description(shortDefinition = "The name of the patient's favourite pet") - private StringType myPetName; + @Child(name = "petName") + @Extension(url = "/petname", definedLocally = false, isModifier = false) + @Description(shortDefinition = "The name of the patient's favourite pet") + private StringType myPetName; - @Child(name = "customid") - @Extension(url = "/customid", definedLocally = false, isModifier = false) - @Description(shortDefinition = "The customid of the patient's ") - private IdType myCustomId; + @Child(name = "customid") + @Extension(url = "/customid", definedLocally = false, isModifier = false) + @Description(shortDefinition = "The customid of the patient's ") + private IdType myCustomId; - public StringType getPetName() { - if (myPetName == null) { - myPetName = new StringType(); + public StringType getPetName() { + if (myPetName == null) { + myPetName = new StringType(); + } + return myPetName; } - return myPetName; - } - public void setPetName(final StringType thePetName) { - myPetName = thePetName; - } - - @Override - public boolean isEmpty() { - return super.isEmpty() && myPetName.isEmpty(); - } - - public IdType getCustomId() { - if (myCustomId == null) { - myCustomId = new IdType(); + public void setPetName(final StringType thePetName) { + myPetName = thePetName; } - return myCustomId; - } - public void setCustomId(final IdType myCustomId) { - this.myCustomId = myCustomId; - } + @Override + 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; + } } diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/ElementWithExtensionR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/ElementWithExtensionR4Test.java new file mode 100644 index 00000000000..be0b0426ad7 --- /dev/null +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/ElementWithExtensionR4Test.java @@ -0,0 +1,224 @@ +package ca.uhn.fhir.parser; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.util.TestUtil; +import org.hl7.fhir.r4.model.*; +import org.junit.AfterClass; +import org.junit.Test; + +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.*; + +/** + * Created by Sébastien Rivière 12/04/2017 + */ +public class ElementWithExtensionR4Test { + + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ElementWithExtensionR4Test.class); + private static FhirContext ourCtx = FhirContext.forR4(); + + @AfterClass + public static void afterClassClearContext() { + TestUtil.clearAllStaticFieldsForUnitTest(); + } + + @Test + public void testNullFlavorPrimitiveExtensionJson() 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.setPetName(new StringType("myPet")); + patient.getExtensionsByUrl("/petname"); + patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK")); + + final StringType stringExt = new StringType(); + 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); + + final IParser parser = ourCtx.newJsonParser().setPrettyPrint(true); + final String json = parser.encodeResourceToString(patient); + + ourLog.info(json); + + patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json); + 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 + public void testNullFlavorPrimitiveExtensionNullValueJson() 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 = ourCtx.newJsonParser().setPrettyPrint(true); + final String json = parser.encodeResourceToString(patient); + + ourLog.info(json); + + patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, json); + assertEquals(1, patient.getPetName().getExtension().size()); + } + + @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.setPetName(new StringType("myPet")); + patient.getExtensionsByUrl("/petname"); + patient.getPetName().addExtension("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor", new StringType("UNK")); + + final StringType stringExt = new StringType(); + 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); + + final IParser parser = ourCtx.newXmlParser().setPrettyPrint(true); + final String xml = parser.encodeResourceToString(patient); + + ourLog.info(xml); + + patient = parser.parseResource(MyPatientWithCustomUrlExtension.class, xml); + 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 + 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 = ourCtx.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 = ourCtx.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 = ourCtx.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 = ourCtx.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 = ourCtx.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()); + } + + @Test + public void testExtensionOnResourceIdXml(){ + Patient p = new Patient(); + p.setActive(true); + p.getIdElement().setValue("123"); + p.getIdElement().addExtension().setUrl("http://foo").setValue(new StringType("FOO")); + + IParser parser = ourCtx.newXmlParser(); + String encoded = parser.encodeResourceToString(p); + assertThat(encoded, containsString("http://foo")); + assertThat(encoded, containsString("FOO")); + + p = (Patient) parser.parseResource(encoded); + assertEquals("Patient/123", p.getId()); + Extension ex = p.getIdElement().getExtension().get(0); + assertEquals("http://foo", ex.getUrl()); + assertEquals("FOO", ex.getValueAsPrimitive().getValueAsString()); + + + } + + @Test + public void testExtensionOnResourceIdJson(){ + Patient p = new Patient(); + p.setActive(true); + p.getIdElement().setValue("123"); + p.getIdElement().addExtension().setUrl("http://foo").setValue(new StringType("FOO")); + + IParser parser = ourCtx.newJsonParser(); + String encoded = parser.encodeResourceToString(p); + assertThat(encoded, containsString("http://foo")); + assertThat(encoded, containsString("FOO")); + + p = (Patient) parser.parseResource(encoded); + assertEquals("Patient/123", p.getId()); + Extension ex = p.getIdElement().getExtension().get(0); + assertEquals("http://foo", ex.getUrl()); + assertEquals("FOO", ex.getValueAsPrimitive().getValueAsString()); + + + } + +} + diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/MyPatientWithCustomUrlExtension.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/MyPatientWithCustomUrlExtension.java new file mode 100644 index 00000000000..a084e39df47 --- /dev/null +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/MyPatientWithCustomUrlExtension.java @@ -0,0 +1,52 @@ +package ca.uhn.fhir.parser; + +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 org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.StringType; + +@ResourceDef() +public class MyPatientWithCustomUrlExtension extends Patient { + + private static final long serialVersionUID = 1L; + + @Child(name = "petName") + @Extension(url = "/petname", definedLocally = false, isModifier = false) + @Description(shortDefinition = "The name of the patient's favourite pet") + private StringType myPetName; + + @Child(name = "customid") + @Extension(url = "/customid", definedLocally = false, isModifier = false) + @Description(shortDefinition = "The customid of the patient's ") + private IdType myCustomId; + + public StringType getPetName() { + if (myPetName == null) { + myPetName = new StringType(); + } + return myPetName; + } + + public void setPetName(final StringType thePetName) { + myPetName = thePetName; + } + + @Override + 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; + } +} diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 59208686b27..16611e9317d 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -279,6 +279,10 @@ Previously my.org was treated as the resource type and Foo was treated as the ID. Thanks to GitHub user @CarthageKing for the pull request! + + Extensions on ID datatypes were not parsed or serialized correctly. Thanks to + Stephen Rivière for the pull request! +