This commit is contained in:
parent
3f2b5fdeb7
commit
1af65ff5a8
|
@ -97,7 +97,7 @@ public abstract class BasePrimitive<T> extends BaseIdentifiableElement implement
|
|||
}
|
||||
|
||||
@Override
|
||||
public IPrimitiveType<T> setValue(T theValue) throws DataFormatException {
|
||||
public BasePrimitive<T> setValue(T theValue) throws DataFormatException {
|
||||
myCoercedValue = theValue;
|
||||
updateStringValue();
|
||||
return this;
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.apache.commons.lang3.Validate;
|
|||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseCoding;
|
||||
import org.hl7.fhir.instance.model.api.IBaseElement;
|
||||
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
|
||||
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
|
||||
import org.hl7.fhir.instance.model.api.IBaseMetaType;
|
||||
|
@ -65,6 +66,7 @@ import ca.uhn.fhir.context.RuntimeChildNarrativeDefinition;
|
|||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.model.api.IIdentifiableElement;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
|
@ -105,10 +107,10 @@ public abstract class BaseParser implements IParser {
|
|||
}
|
||||
|
||||
protected Iterable<CompositeChildElement> compositeChildIterator(IBase theCompositeElement, final boolean theContainedResource, final CompositeChildElement theParent) {
|
||||
|
||||
|
||||
BaseRuntimeElementCompositeDefinition<?> elementDef = (BaseRuntimeElementCompositeDefinition<?>) myContext.getElementDefinition(theCompositeElement.getClass());
|
||||
final List<BaseRuntimeChildDefinition> children = elementDef.getChildrenAndExtension();
|
||||
|
||||
|
||||
return new Iterable<BaseParser.CompositeChildElement>() {
|
||||
@Override
|
||||
public Iterator<CompositeChildElement> iterator() {
|
||||
|
@ -143,9 +145,9 @@ public abstract class BaseParser implements IParser {
|
|||
/*
|
||||
* There are lots of reasons we might skip encoding a particular child
|
||||
*/
|
||||
// if (myNext.getDef().getElementName().equals("extension") || myNext.getDef().getElementName().equals("modifierExtension")) {
|
||||
// myNext = null;
|
||||
// } else
|
||||
// if (myNext.getDef().getElementName().equals("extension") || myNext.getDef().getElementName().equals("modifierExtension")) {
|
||||
// myNext = null;
|
||||
// } else
|
||||
if (myNext.getDef().getElementName().equals("id")) {
|
||||
myNext = null;
|
||||
} else if (!myNext.shouldBeEncoded()) {
|
||||
|
@ -377,7 +379,7 @@ public abstract class BaseParser implements IParser {
|
|||
if (theResource.getStructureFhirVersionEnum() != myContext.getVersion().getVersion()) {
|
||||
throw new IllegalArgumentException("This parser is for FHIR version " + myContext.getVersion().getVersion() + " - Can not encode a structure for version " + theResource.getStructureFhirVersionEnum());
|
||||
}
|
||||
|
||||
|
||||
doEncodeResourceToWriter(theResource, theWriter);
|
||||
}
|
||||
|
||||
|
@ -411,6 +413,18 @@ public abstract class BaseParser implements IParser {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
protected String getCompositeElementId(IBase theElement) {
|
||||
String elementId = null;
|
||||
if (!(theElement instanceof IBaseResource)) {
|
||||
if (theElement instanceof IBaseElement) {
|
||||
elementId = ((IBaseElement) theElement).getId();
|
||||
} else if (theElement instanceof IIdentifiableElement) {
|
||||
elementId = ((IIdentifiableElement) theElement).getElementSpecificId();
|
||||
}
|
||||
}
|
||||
return elementId;
|
||||
}
|
||||
|
||||
ContainedResources getContainedResources() {
|
||||
return myContainedResources;
|
||||
}
|
||||
|
@ -552,14 +566,14 @@ public abstract class BaseParser implements IParser {
|
|||
|
||||
@Override
|
||||
public <T extends IBaseResource> T parseResource(Class<T> theResourceType, Reader theReader) throws DataFormatException {
|
||||
|
||||
|
||||
if (theResourceType != null) {
|
||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(theResourceType);
|
||||
if (def.getStructureVersion() != myContext.getVersion().getVersion()) {
|
||||
throw new IllegalArgumentException("This parser is for FHIR version " + myContext.getVersion().getVersion() + " - Can not parse a structure for version " + def.getStructureVersion());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
T retVal = doParseResource(theResourceType, theReader);
|
||||
|
||||
RuntimeResourceDefinition def = myContext.getResourceDefinition(retVal);
|
||||
|
@ -684,20 +698,20 @@ public abstract class BaseParser implements IParser {
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<IBase> retVal = (List<IBase>) theValues;
|
||||
|
||||
|
||||
for (int i = 0; i < retVal.size(); i++) {
|
||||
IBase next = retVal.get(i);
|
||||
|
||||
|
||||
/*
|
||||
* If we have automatically contained any resources via
|
||||
* their references, this ensures that we output the new
|
||||
* local reference
|
||||
*/
|
||||
if (next instanceof IBaseReference) {
|
||||
IBaseReference nextRef = (IBaseReference)next;
|
||||
IBaseReference nextRef = (IBaseReference) next;
|
||||
String refText = determineReferenceText(nextRef);
|
||||
if (!StringUtils.equals(refText, nextRef.getReferenceElement().getValue())) {
|
||||
|
||||
|
||||
if (retVal == theValues) {
|
||||
retVal = new ArrayList<IBase>(theValues);
|
||||
}
|
||||
|
@ -705,11 +719,11 @@ public abstract class BaseParser implements IParser {
|
|||
myContext.newTerser().cloneInto(nextRef, newRef, true);
|
||||
newRef.setReference(refText);
|
||||
retVal.set(i, newRef);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ import org.hl7.fhir.instance.model.api.IBase;
|
|||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBooleanDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDecimalDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseElement;
|
||||
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
||||
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
|
||||
import org.hl7.fhir.instance.model.api.IBaseHasModifierExtensions;
|
||||
|
@ -140,7 +141,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
myContext = theContext;
|
||||
}
|
||||
|
||||
private void addToHeldComments(int valueIdx, List<String> theCommentsToAdd, ArrayList<ArrayList<String>> theListToAddTo) {
|
||||
private boolean addToHeldComments(int valueIdx, List<String> theCommentsToAdd, ArrayList<ArrayList<String>> theListToAddTo) {
|
||||
if (theCommentsToAdd.size() > 0) {
|
||||
theListToAddTo.ensureCapacity(valueIdx);
|
||||
while (theListToAddTo.size() <= valueIdx) {
|
||||
|
@ -150,10 +151,13 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
theListToAddTo.set(valueIdx, new ArrayList<String>());
|
||||
}
|
||||
theListToAddTo.get(valueIdx).addAll(theCommentsToAdd);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void addToHeldExtensions(int valueIdx, List<? extends IBaseExtension<?, ?>> ext, ArrayList<ArrayList<HeldExtension>> list, boolean theIsModifier) {
|
||||
private boolean addToHeldExtensions(int valueIdx, List<? extends IBaseExtension<?, ?>> ext, ArrayList<ArrayList<HeldExtension>> list, boolean theIsModifier) {
|
||||
if (ext.size() > 0) {
|
||||
list.ensureCapacity(valueIdx);
|
||||
while (list.size() <= valueIdx) {
|
||||
|
@ -165,6 +169,9 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
for (IBaseExtension<?, ?> next : ext) {
|
||||
list.get(valueIdx).add(new HeldExtension(next, theIsModifier));
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,8 +407,8 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
theEventWriter.writeEnd();
|
||||
}
|
||||
|
||||
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theWriter, IBase theNextValue, BaseRuntimeElementDefinition<?> theChildDef, String theChildName, boolean theContainedResource, CompositeChildElement theChildElem)
|
||||
throws IOException {
|
||||
private void encodeChildElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theWriter, IBase theNextValue, BaseRuntimeElementDefinition<?> theChildDef, String theChildName, boolean theContainedResource, CompositeChildElement theChildElem,
|
||||
boolean theForceEmpty) throws IOException {
|
||||
|
||||
switch (theChildDef.getChildType()) {
|
||||
case ID_DATATYPE: {
|
||||
|
@ -420,6 +427,9 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
case PRIMITIVE_DATATYPE: {
|
||||
final IPrimitiveType<?> value = (IPrimitiveType<?>) theNextValue;
|
||||
if (isBlank(value.getValueAsString())) {
|
||||
if (theForceEmpty) {
|
||||
theWriter.writeNull();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -460,7 +470,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case RESOURCE_REF:
|
||||
case RESOURCE_REF:
|
||||
case RESOURCE_BLOCK:
|
||||
case COMPOSITE_DATATYPE: {
|
||||
if (theChildName != null) {
|
||||
|
@ -523,14 +533,20 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
|
||||
}
|
||||
|
||||
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, JsonGenerator theEventWriter, boolean theContainedResource, CompositeChildElement theParent)
|
||||
throws IOException {
|
||||
private void encodeCompositeElementChildrenToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theElement, JsonGenerator theEventWriter, boolean theContainedResource, CompositeChildElement theParent) throws IOException {
|
||||
|
||||
{
|
||||
String elementId = getCompositeElementId(theElement);
|
||||
if (isNotBlank(elementId)) {
|
||||
theEventWriter.write("id", elementId);
|
||||
}
|
||||
}
|
||||
|
||||
boolean haveWrittenExtensions = false;
|
||||
for (CompositeChildElement nextChildElem : super.compositeChildIterator(theElement, theContainedResource, theParent)) {
|
||||
|
||||
BaseRuntimeChildDefinition nextChild = nextChildElem.getDef();
|
||||
|
||||
|
||||
if (nextChildElem.getDef().getElementName().equals("extension") || nextChildElem.getDef().getElementName().equals("modifierExtension") || nextChild instanceof RuntimeChildDeclaredExtensionDefinition) {
|
||||
if (!haveWrittenExtensions) {
|
||||
extractAndWriteExtensionsAsDirectChild(theElement, theEventWriter, myContext.getElementDefinition(theElement.getClass()), theResDef, theResource);
|
||||
|
@ -538,7 +554,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (nextChild instanceof RuntimeChildNarrativeDefinition) {
|
||||
INarrativeGenerator gen = myContext.getNarrativeGenerator();
|
||||
if (gen != null) {
|
||||
|
@ -556,7 +572,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
RuntimeChildNarrativeDefinition child = (RuntimeChildNarrativeDefinition) nextChild;
|
||||
String childName = nextChild.getChildNameByDatatype(child.getDatatype());
|
||||
BaseRuntimeElementDefinition<?> type = child.getChildByName(childName);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, narr, type, childName, theContainedResource, nextChildElem);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, narr, type, childName, theContainedResource, nextChildElem, false);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -564,7 +580,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
} else if (nextChild instanceof RuntimeChildContainedResources) {
|
||||
String childName = nextChild.getValidChildNames().iterator().next();
|
||||
BaseRuntimeElementDefinition<?> child = nextChild.getChildByName(childName);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, null, child, childName, theContainedResource, nextChildElem);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, null, child, childName, theContainedResource, nextChildElem, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -581,6 +597,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
ArrayList<ArrayList<HeldExtension>> extensions = new ArrayList<ArrayList<HeldExtension>>(0);
|
||||
ArrayList<ArrayList<HeldExtension>> modifierExtensions = new ArrayList<ArrayList<HeldExtension>>(0);
|
||||
ArrayList<ArrayList<String>> comments = new ArrayList<ArrayList<String>>(0);
|
||||
ArrayList<String> ids = new ArrayList<String>(0);
|
||||
|
||||
int valueIdx = 0;
|
||||
for (IBase nextValue : values) {
|
||||
|
@ -596,13 +613,10 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
|
||||
Class<? extends IBase> type = nextValue.getClass();
|
||||
|
||||
|
||||
String childName = nextChild.getChildNameByDatatype(type);
|
||||
BaseRuntimeElementDefinition<?> childDef = nextChild.getChildElementDefinitionByDatatype(type);
|
||||
if (childDef == null) {
|
||||
// if (IBaseExtension.class.isAssignableFrom(type)) {
|
||||
// continue;
|
||||
// }
|
||||
super.throwExceptionForUnknownChildType(nextChild, type);
|
||||
}
|
||||
boolean primitive = childDef.getChildType() == ChildTypeEnum.PRIMITIVE_DATATYPE;
|
||||
|
@ -611,55 +625,54 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
continue;
|
||||
}
|
||||
|
||||
// if (nextChild instanceof RuntimeChildDeclaredExtensionDefinition) {
|
||||
// RuntimeChildDeclaredExtensionDefinition extDef = (RuntimeChildDeclaredExtensionDefinition) nextChild;
|
||||
// new HeldExtension(extDef, nextValue).write(theResDef, theResource, theEventWriter);
|
||||
// } else {
|
||||
boolean force = false;
|
||||
if (primitive) {
|
||||
if (nextValue instanceof ISupportsUndeclaredExtensions) {
|
||||
List<ExtensionDt> ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredExtensions();
|
||||
force |= addToHeldExtensions(valueIdx, ext, extensions, false);
|
||||
|
||||
if (currentChildName == null || !currentChildName.equals(childName)) {
|
||||
if (inArray) {
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
if (nextChild.getMax() > 1 || nextChild.getMax() == Child.MAX_UNLIMITED) {
|
||||
theEventWriter.writeStartArray(childName);
|
||||
inArray = true;
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theContainedResource, nextChildElem);
|
||||
} else if (nextChild instanceof RuntimeChildNarrativeDefinition && theContainedResource) {
|
||||
// suppress narratives from contained resources
|
||||
} else {
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, childName, theContainedResource, nextChildElem);
|
||||
}
|
||||
currentChildName = childName;
|
||||
ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredModifierExtensions();
|
||||
force |= addToHeldExtensions(valueIdx, ext, modifierExtensions, true);
|
||||
} else {
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theContainedResource, nextChildElem);
|
||||
}
|
||||
|
||||
if (primitive) {
|
||||
if (nextValue instanceof ISupportsUndeclaredExtensions) {
|
||||
List<ExtensionDt> ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredExtensions();
|
||||
addToHeldExtensions(valueIdx, ext, extensions, false);
|
||||
|
||||
ext = ((ISupportsUndeclaredExtensions) nextValue).getUndeclaredModifierExtensions();
|
||||
addToHeldExtensions(valueIdx, ext, modifierExtensions, true);
|
||||
} else {
|
||||
if (nextValue instanceof IBaseHasExtensions) {
|
||||
IBaseHasExtensions element = (IBaseHasExtensions) nextValue;
|
||||
List<? extends IBaseExtension<?, ?>> ext = element.getExtension();
|
||||
addToHeldExtensions(valueIdx, ext, extensions, false);
|
||||
}
|
||||
if (nextValue instanceof IBaseHasModifierExtensions) {
|
||||
IBaseHasModifierExtensions element = (IBaseHasModifierExtensions) nextValue;
|
||||
List<? extends IBaseExtension<?, ?>> ext = element.getModifierExtension();
|
||||
addToHeldExtensions(valueIdx, ext, extensions, true);
|
||||
}
|
||||
if (nextValue instanceof IBaseHasExtensions) {
|
||||
IBaseHasExtensions element = (IBaseHasExtensions) nextValue;
|
||||
List<? extends IBaseExtension<?, ?>> ext = element.getExtension();
|
||||
force |= addToHeldExtensions(valueIdx, ext, extensions, false);
|
||||
}
|
||||
if (nextValue.hasFormatComment()) {
|
||||
addToHeldComments(valueIdx, nextValue.getFormatCommentsPre(), comments);
|
||||
addToHeldComments(valueIdx, nextValue.getFormatCommentsPost(), comments);
|
||||
if (nextValue instanceof IBaseHasModifierExtensions) {
|
||||
IBaseHasModifierExtensions element = (IBaseHasModifierExtensions) nextValue;
|
||||
List<? extends IBaseExtension<?, ?>> ext = element.getModifierExtension();
|
||||
force |= addToHeldExtensions(valueIdx, ext, extensions, true);
|
||||
}
|
||||
}
|
||||
if (nextValue.hasFormatComment()) {
|
||||
force |= addToHeldComments(valueIdx, nextValue.getFormatCommentsPre(), comments);
|
||||
force |= addToHeldComments(valueIdx, nextValue.getFormatCommentsPost(), comments);
|
||||
}
|
||||
String elementId = getCompositeElementId(nextValue);
|
||||
if (isNotBlank(elementId)) {
|
||||
force = true;
|
||||
addToHeldIds(valueIdx, ids, elementId);
|
||||
}
|
||||
}
|
||||
|
||||
// }
|
||||
if (currentChildName == null || !currentChildName.equals(childName)) {
|
||||
if (inArray) {
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
if (nextChild.getMax() > 1 || nextChild.getMax() == Child.MAX_UNLIMITED) {
|
||||
theEventWriter.writeStartArray(childName);
|
||||
inArray = true;
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theContainedResource, nextChildElem, force);
|
||||
} else if (nextChild instanceof RuntimeChildNarrativeDefinition && theContainedResource) {
|
||||
// suppress narratives from contained resources
|
||||
} else {
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, childName, theContainedResource, nextChildElem, force);
|
||||
}
|
||||
currentChildName = childName;
|
||||
} else {
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, nextValue, childDef, null, theContainedResource, nextChildElem, force);
|
||||
}
|
||||
|
||||
valueIdx++;
|
||||
}
|
||||
|
@ -701,12 +714,21 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
haveContent = true;
|
||||
}
|
||||
|
||||
String elementId = null;
|
||||
if (ids.size() > i) {
|
||||
elementId = ids.get(i);
|
||||
haveContent |= isNotBlank(elementId);
|
||||
}
|
||||
|
||||
if (!haveContent) {
|
||||
theEventWriter.writeNull();
|
||||
} else {
|
||||
if (inArray) {
|
||||
theEventWriter.writeStartObject();
|
||||
}
|
||||
if (isNotBlank(elementId)) {
|
||||
theEventWriter.write("id", elementId);
|
||||
}
|
||||
if (nextComments != null && !nextComments.isEmpty()) {
|
||||
theEventWriter.writeStartArray("fhir_comments");
|
||||
for (String next : nextComments) {
|
||||
|
@ -726,8 +748,17 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter, boolean theContainedResource, CompositeChildElement theParent)
|
||||
throws IOException, DataFormatException {
|
||||
private void addToHeldIds(int theValueIdx, ArrayList<String> theListToAddTo, String theId) {
|
||||
theListToAddTo.ensureCapacity(theValueIdx);
|
||||
while (theListToAddTo.size() <= theValueIdx) {
|
||||
theListToAddTo.add(null);
|
||||
}
|
||||
if (theListToAddTo.get(theValueIdx) == null) {
|
||||
theListToAddTo.set(theValueIdx, theId);
|
||||
}
|
||||
}
|
||||
|
||||
private void encodeCompositeElementToStreamWriter(RuntimeResourceDefinition theResDef, IBaseResource theResource, IBase theNextValue, JsonGenerator theEventWriter, boolean theContainedResource, CompositeChildElement theParent) throws IOException, DataFormatException {
|
||||
|
||||
writeCommentsPreAndPost(theNextValue, theEventWriter);
|
||||
encodeCompositeElementChildrenToStreamWriter(theResDef, theResource, theNextValue, theEventWriter, theContainedResource, theParent);
|
||||
|
@ -802,7 +833,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
List<BaseCodingDt> securityLabels = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.SECURITY_LABELS);
|
||||
List<? extends IIdType> profiles = extractMetadataListNotNull(resource, ResourceMetadataKeyEnum.PROFILES);
|
||||
profiles = super.getProfileTagsForEncoding(resource, profiles);
|
||||
|
||||
|
||||
TagList tags = getMetaTagsForEncoding(resource);
|
||||
InstantDt updated = (InstantDt) resource.getResourceMetadata().get(ResourceMetadataKeyEnum.UPDATED);
|
||||
IdDt resourceId = resource.getId();
|
||||
|
@ -1305,6 +1336,9 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
theState.endingElement();
|
||||
break;
|
||||
case NULL:
|
||||
theState.enteringNewElement(null, theName);
|
||||
parseAlternates(theAlternateVal, theState, theAlternateName);
|
||||
theState.endingElement();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1564,7 +1598,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
|
||||
public void write(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter) throws IOException {
|
||||
if (myUndeclaredExtension != null) {
|
||||
writeUndeclaredExtInDstu1Format(theResDef, theResource, theEventWriter, myUndeclaredExtension);
|
||||
writeUndeclaredExtension(theResDef, theResource, theEventWriter, myUndeclaredExtension);
|
||||
} else {
|
||||
theEventWriter.writeStartObject();
|
||||
|
||||
|
@ -1577,14 +1611,14 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
extractAndWriteExtensionsAsDirectChild(myValue, theEventWriter, def, theResDef, theResource);
|
||||
} else {
|
||||
String childName = myDef.getChildNameByDatatype(myValue.getClass());
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName, false, null);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, myValue, def, childName, false, null, false);
|
||||
}
|
||||
|
||||
theEventWriter.writeEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeUndeclaredExtInDstu1Format(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, IBaseExtension<?, ?> ext) throws IOException {
|
||||
private void writeUndeclaredExtension(RuntimeResourceDefinition theResDef, IBaseResource theResource, JsonGenerator theEventWriter, IBaseExtension<?, ?> ext) throws IOException {
|
||||
IBase value = ext.getValue();
|
||||
String extensionUrl = ext.getUrl();
|
||||
|
||||
|
@ -1592,6 +1626,11 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
|
||||
writeCommentsPreAndPost(myUndeclaredExtension, theEventWriter);
|
||||
|
||||
String elementId = getCompositeElementId(ext);
|
||||
if (isNotBlank(elementId)) {
|
||||
theEventWriter.write("id", getCompositeElementId(ext));
|
||||
}
|
||||
|
||||
theEventWriter.write("url", extensionUrl);
|
||||
|
||||
boolean noValue = value == null || value.isEmpty();
|
||||
|
@ -1606,17 +1645,17 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
}
|
||||
|
||||
for (Object next : ext.getExtension()) {
|
||||
writeUndeclaredExtInDstu1Format(theResDef, theResource, theEventWriter, (IBaseExtension<?, ?>) next);
|
||||
writeUndeclaredExtension(theResDef, theResource, theEventWriter, (IBaseExtension<?, ?>) next);
|
||||
}
|
||||
theEventWriter.writeEnd();
|
||||
} else {
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
* Pre-process value - This is called in case the value is a reference
|
||||
* since we might modify the text
|
||||
* since we might modify the text
|
||||
*/
|
||||
value = JsonParser.super.preProcessValues(myDef, theResource, Collections.singletonList(value)).get(0);
|
||||
|
||||
|
||||
RuntimeChildUndeclaredExtensionDefinition extDef = myContext.getRuntimeChildUndeclaredExtensionDefinition();
|
||||
String childName = extDef.getChildNameByDatatype(value.getClass());
|
||||
if (childName == null) {
|
||||
|
@ -1626,7 +1665,7 @@ public class JsonParser extends BaseParser implements IParser {
|
|||
if (childDef == null) {
|
||||
throw new ConfigurationException("Unable to encode extension, unregognized child element type: " + value.getClass().getCanonicalName());
|
||||
}
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName, true, null);
|
||||
encodeChildElementToStreamWriter(theResDef, theResource, theEventWriter, value, childDef, childName, true, null, false);
|
||||
}
|
||||
|
||||
// theEventWriter.name(myUndeclaredExtension.get);
|
||||
|
|
|
@ -94,15 +94,15 @@ import ca.uhn.fhir.util.IModelVisitor;
|
|||
class ParserState<T> {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ParserState.class);
|
||||
|
||||
private List<String> myComments = new ArrayList<String>(2);
|
||||
private final FhirContext myContext;
|
||||
private final IParserErrorHandler myErrorHandler;
|
||||
private final boolean myJsonMode;
|
||||
private T myObject;
|
||||
private BaseState myState;
|
||||
private IBase myPreviousElement;
|
||||
private final IParser myParser;
|
||||
|
||||
private IBase myPreviousElement;
|
||||
private BaseState myState;
|
||||
private ParserState(IParser theParser, FhirContext theContext, boolean theJsonMode, IParserErrorHandler theErrorHandler) {
|
||||
myParser = theParser;
|
||||
myContext = theContext;
|
||||
|
@ -1121,10 +1121,6 @@ class ParserState<T> {
|
|||
}
|
||||
}
|
||||
|
||||
protected BundleEntry getEntry() {
|
||||
return myEntry;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void populateResourceMetadata() {
|
||||
if (myEntry.getResource() == null) {
|
||||
|
@ -1624,6 +1620,13 @@ class ParserState<T> {
|
|||
try {
|
||||
child = myDefinition.getChildByNameOrThrowDataFormatException(theChildName);
|
||||
} catch (DataFormatException e) {
|
||||
if (theChildName.equals("id")) {
|
||||
if (getCurrentElement() instanceof IIdentifiableElement) {
|
||||
push(new IdentifiableElementIdState(getPreResourceState(), (IIdentifiableElement) getCurrentElement()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This means we've found an element that doesn't exist on the structure. If the error handler doesn't throw
|
||||
* an exception, swallow the element silently along with any child elements
|
||||
|
@ -1751,6 +1754,27 @@ class ParserState<T> {
|
|||
|
||||
}
|
||||
|
||||
public class ElementIdState extends BaseState {
|
||||
|
||||
private IBaseElement myElement;
|
||||
|
||||
public ElementIdState(ParserState<T>.PreResourceState thePreResourceState, IBaseElement theElement) {
|
||||
super(thePreResourceState);
|
||||
myElement = theElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeValue(String theName, String theValue) throws DataFormatException {
|
||||
myElement.setId(theValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() {
|
||||
pop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class ExtensionState extends BaseState {
|
||||
|
||||
private IBaseExtension<?, ?> myExtension;
|
||||
|
@ -1767,6 +1791,15 @@ class ParserState<T> {
|
|||
// of "value" like every single other place
|
||||
return;
|
||||
}
|
||||
if ("id".equals(theName)) {
|
||||
if (getCurrentElement() instanceof IBaseElement) {
|
||||
((IBaseElement)getCurrentElement()).setId(theValue);
|
||||
return;
|
||||
} else if (getCurrentElement() instanceof IIdentifiableElement) {
|
||||
((IIdentifiableElement)getCurrentElement()).setElementSpecificId(theValue);
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.attributeValue(theName, theValue);
|
||||
}
|
||||
|
||||
|
@ -1780,6 +1813,16 @@ class ParserState<T> {
|
|||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException {
|
||||
if (theLocalPart.equals("id")) {
|
||||
if (getCurrentElement() instanceof IBaseElement) {
|
||||
push(new ElementIdState(getPreResourceState(), (IBaseElement)getCurrentElement()));
|
||||
return;
|
||||
} else if (getCurrentElement() instanceof IIdentifiableElement) {
|
||||
push(new IdentifiableElementIdState(getPreResourceState(), (IIdentifiableElement)getCurrentElement()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BaseRuntimeElementDefinition<?> target = myContext.getRuntimeChildUndeclaredExtensionDefinition().getChildByName(theLocalPart);
|
||||
if (target == null) {
|
||||
myErrorHandler.unknownElement(null, theLocalPart);
|
||||
|
@ -1836,6 +1879,27 @@ class ParserState<T> {
|
|||
|
||||
}
|
||||
|
||||
public class IdentifiableElementIdState extends BaseState {
|
||||
|
||||
private IIdentifiableElement myElement;
|
||||
|
||||
public IdentifiableElementIdState(ParserState<T>.PreResourceState thePreResourceState, IIdentifiableElement theElement) {
|
||||
super(thePreResourceState);
|
||||
myElement = theElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeValue(String theName, String theValue) throws DataFormatException {
|
||||
myElement.setElementSpecificId(theValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endingElement() {
|
||||
pop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class MetaElementState extends BaseState {
|
||||
private ResourceMetadataMap myMap;
|
||||
|
||||
|
|
|
@ -518,6 +518,10 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
String value = pd.getValueAsString();
|
||||
if (value != null || super.hasExtensions(pd)) {
|
||||
theEventWriter.writeStartElement(childName);
|
||||
String elementId = getCompositeElementId(theElement);
|
||||
if (isNotBlank(elementId)) {
|
||||
theEventWriter.writeAttribute("id", elementId);
|
||||
}
|
||||
if (value != null) {
|
||||
theEventWriter.writeAttribute("value", value);
|
||||
}
|
||||
|
@ -530,10 +534,13 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
case RESOURCE_BLOCK:
|
||||
case COMPOSITE_DATATYPE: {
|
||||
theEventWriter.writeStartElement(childName);
|
||||
String elementId = getCompositeElementId(theElement);
|
||||
if (isNotBlank(elementId)) {
|
||||
theEventWriter.writeAttribute("id", elementId);
|
||||
}
|
||||
if (isNotBlank(theExtensionUrl)) {
|
||||
theEventWriter.writeAttribute("url", theExtensionUrl);
|
||||
}
|
||||
BaseRuntimeElementCompositeDefinition<?> childCompositeDef = (BaseRuntimeElementCompositeDefinition<?>) childDef;
|
||||
encodeCompositeElementToStreamWriter(theResource, theElement, theEventWriter, theIncludedResource, theParent);
|
||||
theEventWriter.writeEndElement();
|
||||
break;
|
||||
|
@ -592,6 +599,7 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
@SuppressWarnings("rawtypes")
|
||||
private void encodeCompositeElementToStreamWriter(IBaseResource theResource, IBase theElement, XMLStreamWriter theEventWriter, boolean theContainedResource, CompositeChildElement theParent)
|
||||
throws XMLStreamException, DataFormatException {
|
||||
|
||||
for (CompositeChildElement nextChildElem : super.compositeChildIterator(theElement, theContainedResource, theParent)) {
|
||||
|
||||
BaseRuntimeChildDefinition nextChild = nextChildElem.getDef();
|
||||
|
@ -701,6 +709,11 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
theEventWriter.writeStartElement("extension");
|
||||
}
|
||||
|
||||
String elementId = getCompositeElementId(nextValue);
|
||||
if (isNotBlank(elementId)) {
|
||||
theEventWriter.writeAttribute("id", elementId);
|
||||
}
|
||||
|
||||
theEventWriter.writeAttribute("url", extensionUrl);
|
||||
encodeChildElementToStreamWriter(theResource, theEventWriter, nextValue, childName, childDef, null, theContainedResource, nextChildElem);
|
||||
theEventWriter.writeEndElement();
|
||||
|
@ -892,18 +905,23 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
}
|
||||
}
|
||||
|
||||
private void encodeUndeclaredExtensions(IBaseResource theResource, XMLStreamWriter theWriter, List<? extends IBaseExtension<?, ?>> theExtensions, String tagName, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
private void encodeUndeclaredExtensions(IBaseResource theResource, XMLStreamWriter theEventWriter, List<? extends IBaseExtension<?, ?>> theExtensions, String tagName, boolean theIncludedResource) throws XMLStreamException, DataFormatException {
|
||||
for (IBaseExtension<?, ?> next : theExtensions) {
|
||||
if (next == null || (ElementUtil.isEmpty(next.getValue()) && next.getExtension().isEmpty())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
writeCommentsPre(theWriter, next);
|
||||
writeCommentsPre(theEventWriter, next);
|
||||
|
||||
theWriter.writeStartElement(tagName);
|
||||
theEventWriter.writeStartElement(tagName);
|
||||
|
||||
String elementId = getCompositeElementId(next);
|
||||
if (isNotBlank(elementId)) {
|
||||
theEventWriter.writeAttribute("id", elementId);
|
||||
}
|
||||
|
||||
String url = next.getUrl();
|
||||
theWriter.writeAttribute("url", url);
|
||||
theEventWriter.writeAttribute("url", url);
|
||||
|
||||
if (next.getValue() != null) {
|
||||
IBaseDatatype value = next.getValue();
|
||||
|
@ -923,15 +941,15 @@ public class XmlParser extends BaseParser implements IParser {
|
|||
throw new ConfigurationException("Unable to encode extension, unrecognized child element type: " + value.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
encodeChildElementToStreamWriter(theResource, theWriter, value, childName, childDef, null, theIncludedResource, null);
|
||||
encodeChildElementToStreamWriter(theResource, theEventWriter, value, childName, childDef, null, theIncludedResource, null);
|
||||
}
|
||||
|
||||
// child extensions
|
||||
encodeExtensionsIfPresent(theResource, theWriter, next, theIncludedResource);
|
||||
encodeExtensionsIfPresent(theResource, theEventWriter, next, theIncludedResource);
|
||||
|
||||
theWriter.writeEndElement();
|
||||
theEventWriter.writeEndElement();
|
||||
|
||||
writeCommentsPost(theWriter, next);
|
||||
writeCommentsPost(theEventWriter, next);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,4 +24,6 @@ public interface IBaseElement {
|
|||
|
||||
IBaseElement setId(String theValue);
|
||||
|
||||
String getId();
|
||||
|
||||
}
|
||||
|
|
|
@ -83,6 +83,63 @@ public class JsonParserDstu2Test {
|
|||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
/**
|
||||
* See #336
|
||||
*/
|
||||
@Test
|
||||
public void testEncodeAndParseNullPrimitiveWithExtensions() {
|
||||
|
||||
Patient p = new Patient();
|
||||
p.setId("patid");
|
||||
HumanNameDt name = p.addName();
|
||||
name.addFamily().setValue(null).addUndeclaredExtension(new ExtensionDt(false, "http://foo", new StringDt("FOOEXT0")));
|
||||
name.getFamily().get(0).setElementSpecificId("f0");
|
||||
name.addFamily().setValue("V1").addUndeclaredExtension((ExtensionDt) new ExtensionDt(false, "http://foo", new StringDt("FOOEXT1")));
|
||||
name.getFamily().get(1).setElementSpecificId("f1");
|
||||
name.getFamily().get(1).getUndeclaredExtensions().get(0).setElementSpecificId("ext1id");
|
||||
name.addFamily(); // this one shouldn't get encoded
|
||||
name.addFamily().setValue(null).addUndeclaredExtension(new ExtensionDt(false, "http://foo", new StringDt("FOOEXT3")));
|
||||
name.setElementSpecificId("nameid");
|
||||
|
||||
String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p);
|
||||
ourLog.info(output);
|
||||
|
||||
output = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(p);
|
||||
String expected = "{\"resourceType\":\"Patient\",\"id\":\"patid\",\"name\":[{\"id\":\"nameid\",\"family\":[null,\"V1\",null],\"_family\":[{\"id\":\"f0\",\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"FOOEXT0\"}]},{\"id\":\"f1\",\"extension\":[{\"id\":\"ext1id\",\"url\":\"http://foo\",\"valueString\":\"FOOEXT1\"}]},{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"FOOEXT3\"}]}]}]}";
|
||||
assertEquals(expected, output);
|
||||
|
||||
p = ourCtx.newJsonParser().parseResource(Patient.class, output);
|
||||
assertEquals("patid", p.getIdElement().getIdPart());
|
||||
|
||||
name = p.getName().get(0);
|
||||
assertEquals("nameid", name.getElementSpecificId());
|
||||
assertEquals(3, name.getFamily().size());
|
||||
|
||||
assertEquals(null, name.getFamily().get(0).getValue());
|
||||
assertEquals("V1", name.getFamily().get(1).getValue());
|
||||
assertEquals(null, name.getFamily().get(2).getValue());
|
||||
|
||||
assertEquals("f0", name.getFamily().get(0).getElementSpecificId());
|
||||
assertEquals("f1", name.getFamily().get(1).getElementSpecificId());
|
||||
assertEquals(null, name.getFamily().get(2).getElementSpecificId());
|
||||
|
||||
assertEquals(1, name.getFamily().get(0).getAllUndeclaredExtensions().size());
|
||||
assertEquals("http://foo", name.getFamily().get(0).getAllUndeclaredExtensions().get(0).getUrl());
|
||||
assertEquals("FOOEXT0", ((StringDt)name.getFamily().get(0).getAllUndeclaredExtensions().get(0).getValue()).getValue());
|
||||
assertEquals(null, name.getFamily().get(0).getAllUndeclaredExtensions().get(0).getElementSpecificId());
|
||||
|
||||
assertEquals(1, name.getFamily().get(1).getAllUndeclaredExtensions().size());
|
||||
assertEquals("http://foo", name.getFamily().get(1).getAllUndeclaredExtensions().get(0).getUrl());
|
||||
assertEquals("FOOEXT1", ((StringDt)name.getFamily().get(1).getAllUndeclaredExtensions().get(0).getValue()).getValue());
|
||||
assertEquals("ext1id", name.getFamily().get(1).getAllUndeclaredExtensions().get(0).getElementSpecificId());
|
||||
|
||||
assertEquals(1, name.getFamily().get(2).getAllUndeclaredExtensions().size());
|
||||
assertEquals("http://foo", name.getFamily().get(2).getAllUndeclaredExtensions().get(0).getUrl());
|
||||
assertEquals("FOOEXT3", ((StringDt)name.getFamily().get(2).getAllUndeclaredExtensions().get(0).getValue()).getValue());
|
||||
assertEquals(null, name.getFamily().get(2).getAllUndeclaredExtensions().get(0).getElementSpecificId());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testContainedResourceInExtensionUndeclared() {
|
||||
|
|
|
@ -112,6 +112,62 @@ public class XmlParserDstu2Test {
|
|||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
/**
|
||||
* See #336
|
||||
*/
|
||||
@Test
|
||||
public void testEncodeAndParseNullPrimitiveWithExtensions() {
|
||||
|
||||
Patient p = new Patient();
|
||||
p.setId("patid");
|
||||
HumanNameDt name = p.addName();
|
||||
name.addFamily().setValue(null).addUndeclaredExtension(new ExtensionDt(false, "http://foo", new StringDt("FOOEXT0")));
|
||||
name.getFamily().get(0).setElementSpecificId("f0");
|
||||
name.addFamily().setValue("V1").addUndeclaredExtension((ExtensionDt) new ExtensionDt(false, "http://foo", new StringDt("FOOEXT1")));
|
||||
name.getFamily().get(1).setElementSpecificId("f1");
|
||||
name.getFamily().get(1).getUndeclaredExtensions().get(0).setElementSpecificId("ext1id");
|
||||
name.addFamily(); // this one shouldn't get encoded
|
||||
name.addFamily().setValue(null).addUndeclaredExtension(new ExtensionDt(false, "http://foo", new StringDt("FOOEXT3")));
|
||||
name.setElementSpecificId("nameid");
|
||||
|
||||
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p);
|
||||
ourLog.info(output);
|
||||
|
||||
output = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(p);
|
||||
String expected = "<Patient xmlns=\"http://hl7.org/fhir\"><id value=\"patid\"/><name id=\"nameid\"><family id=\"f0\"><extension url=\"http://foo\"><valueString value=\"FOOEXT0\"/></extension></family><family id=\"f1\" value=\"V1\"><extension id=\"ext1id\" url=\"http://foo\"><valueString value=\"FOOEXT1\"/></extension></family><family><extension url=\"http://foo\"><valueString value=\"FOOEXT3\"/></extension></family></name></Patient>";
|
||||
assertEquals(expected, output);
|
||||
|
||||
p = ourCtx.newXmlParser().parseResource(Patient.class, output);
|
||||
assertEquals("patid", p.getIdElement().getIdPart());
|
||||
|
||||
name = p.getName().get(0);
|
||||
assertEquals("nameid", name.getElementSpecificId());
|
||||
assertEquals(3, name.getFamily().size());
|
||||
|
||||
assertEquals(null, name.getFamily().get(0).getValue());
|
||||
assertEquals("V1", name.getFamily().get(1).getValue());
|
||||
assertEquals(null, name.getFamily().get(2).getValue());
|
||||
|
||||
assertEquals("f0", name.getFamily().get(0).getElementSpecificId());
|
||||
assertEquals("f1", name.getFamily().get(1).getElementSpecificId());
|
||||
assertEquals(null, name.getFamily().get(2).getElementSpecificId());
|
||||
|
||||
assertEquals(1, name.getFamily().get(0).getAllUndeclaredExtensions().size());
|
||||
assertEquals("http://foo", name.getFamily().get(0).getAllUndeclaredExtensions().get(0).getUrl());
|
||||
assertEquals("FOOEXT0", ((StringDt)name.getFamily().get(0).getAllUndeclaredExtensions().get(0).getValue()).getValue());
|
||||
assertEquals(null, name.getFamily().get(0).getAllUndeclaredExtensions().get(0).getElementSpecificId());
|
||||
|
||||
assertEquals(1, name.getFamily().get(1).getAllUndeclaredExtensions().size());
|
||||
assertEquals("http://foo", name.getFamily().get(1).getAllUndeclaredExtensions().get(0).getUrl());
|
||||
assertEquals("FOOEXT1", ((StringDt)name.getFamily().get(1).getAllUndeclaredExtensions().get(0).getValue()).getValue());
|
||||
assertEquals("ext1id", name.getFamily().get(1).getAllUndeclaredExtensions().get(0).getElementSpecificId());
|
||||
|
||||
assertEquals(1, name.getFamily().get(2).getAllUndeclaredExtensions().size());
|
||||
assertEquals("http://foo", name.getFamily().get(2).getAllUndeclaredExtensions().get(0).getUrl());
|
||||
assertEquals("FOOEXT3", ((StringDt)name.getFamily().get(2).getAllUndeclaredExtensions().get(0).getValue()).getValue());
|
||||
assertEquals(null, name.getFamily().get(2).getAllUndeclaredExtensions().get(0).getElementSpecificId());
|
||||
|
||||
}
|
||||
|
||||
@ResourceDef(name="Patient")
|
||||
public static class TestPatientFor327 extends Patient
|
||||
|
|
|
@ -43,7 +43,7 @@ import org.hl7.fhir.dstu3.exceptions.FHIRException;
|
|||
/**
|
||||
* Base definition for all elements in a resource.
|
||||
*/
|
||||
public abstract class Element extends Base implements IBaseHasExtensions {
|
||||
public abstract class Element extends Base implements IBaseHasExtensions, IBaseElement {
|
||||
|
||||
/**
|
||||
* unique id for the element within a resource (for internal references).
|
||||
|
|
|
@ -82,12 +82,79 @@ public class JsonParserDstu3Test {
|
|||
ourCtx.setNarrativeGenerator(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* See #336
|
||||
*/
|
||||
@Test
|
||||
public void testEncodeAndParseNullPrimitiveWithExtensions() {
|
||||
|
||||
Patient p = new Patient();
|
||||
p.setId("patid");
|
||||
HumanName name = p.addName();
|
||||
name.addFamilyElement().setValue(null).setId("f0").addExtension(new Extension("http://foo", new StringType("FOOEXT0")));
|
||||
name.addFamilyElement().setValue("V1").setId("f1").addExtension((Extension) new Extension("http://foo", new StringType("FOOEXT1")).setId("ext1id"));
|
||||
name.addFamilyElement(); // this one shouldn't get encoded
|
||||
name.addFamilyElement().setValue(null).addExtension(new Extension("http://foo", new StringType("FOOEXT3")));
|
||||
name.setId("nameid");
|
||||
|
||||
String output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p);
|
||||
ourLog.info(output);
|
||||
|
||||
output = ourCtx.newJsonParser().setPrettyPrint(false).encodeResourceToString(p);
|
||||
String expected = "{\"resourceType\":\"Patient\",\"id\":\"patid\",\"name\":[{\"id\":\"nameid\",\"family\":[null,\"V1\",null],\"_family\":[{\"id\":\"f0\",\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"FOOEXT0\"}]},{\"id\":\"f1\",\"extension\":[{\"id\":\"ext1id\",\"url\":\"http://foo\",\"valueString\":\"FOOEXT1\"}]},{\"extension\":[{\"url\":\"http://foo\",\"valueString\":\"FOOEXT3\"}]}]}]}";
|
||||
assertEquals(expected, output);
|
||||
|
||||
p = ourCtx.newJsonParser().parseResource(Patient.class, output);
|
||||
assertEquals("patid", p.getIdElement().getIdPart());
|
||||
|
||||
name = p.getName().get(0);
|
||||
assertEquals("nameid", name.getId());
|
||||
assertEquals(3, name.getFamily().size());
|
||||
|
||||
assertEquals(null, name.getFamily().get(0).getValue());
|
||||
assertEquals("V1", name.getFamily().get(1).getValue());
|
||||
assertEquals(null, name.getFamily().get(2).getValue());
|
||||
|
||||
assertEquals("f0", name.getFamily().get(0).getId());
|
||||
assertEquals("f1", name.getFamily().get(1).getId());
|
||||
assertEquals(null, name.getFamily().get(2).getId());
|
||||
|
||||
assertEquals(1, name.getFamily().get(0).getExtension().size());
|
||||
assertEquals("http://foo", name.getFamily().get(0).getExtension().get(0).getUrl());
|
||||
assertEquals("FOOEXT0", ((StringType)name.getFamily().get(0).getExtension().get(0).getValue()).getValue());
|
||||
assertEquals(null, name.getFamily().get(0).getExtension().get(0).getId());
|
||||
|
||||
assertEquals(1, name.getFamily().get(1).getExtension().size());
|
||||
assertEquals("http://foo", name.getFamily().get(1).getExtension().get(0).getUrl());
|
||||
assertEquals("FOOEXT1", ((StringType)name.getFamily().get(1).getExtension().get(0).getValue()).getValue());
|
||||
assertEquals("ext1id", name.getFamily().get(1).getExtension().get(0).getId());
|
||||
|
||||
assertEquals(1, name.getFamily().get(2).getExtension().size());
|
||||
assertEquals("http://foo", name.getFamily().get(2).getExtension().get(0).getUrl());
|
||||
assertEquals("FOOEXT3", ((StringType)name.getFamily().get(2).getExtension().get(0).getValue()).getValue());
|
||||
assertEquals(null, name.getFamily().get(2).getExtension().get(0).getId());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void afterClassClearContext() {
|
||||
TestUtil.clearAllStaticFieldsForUnitTest();
|
||||
}
|
||||
|
||||
/**
|
||||
* See #335
|
||||
*/
|
||||
@Test
|
||||
public void testParseExtensionWithId() throws Exception {
|
||||
String input = IOUtils.toString(getClass().getResourceAsStream("/json-edge-case-modified-335.json"));
|
||||
|
||||
Patient p = ourCtx.newJsonParser().parseResource(Patient.class, input);
|
||||
StringType family1 = p.getContact().get(0).getName().getFamily().get(1);
|
||||
assertEquals("du", family1.getValue());
|
||||
assertEquals("a2", family1.getId());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEncodeAndParseExtensions() throws Exception {
|
||||
|
|
|
@ -562,6 +562,60 @@ public class XmlParserDstu3Test {
|
|||
assertEquals("label2", tagList.get(1).getDisplay());
|
||||
}
|
||||
|
||||
/**
|
||||
* See #336
|
||||
*/
|
||||
@Test
|
||||
public void testEncodeAndParseNullPrimitiveWithExtensions() {
|
||||
|
||||
Patient p = new Patient();
|
||||
p.setId("patid");
|
||||
HumanName name = p.addName();
|
||||
name.addFamilyElement().setValue(null).setId("f0").addExtension(new Extension("http://foo", new StringType("FOOEXT0")));
|
||||
name.addFamilyElement().setValue("V1").setId("f1").addExtension((Extension) new Extension("http://foo", new StringType("FOOEXT1")).setId("ext1id"));
|
||||
name.addFamilyElement(); // this one shouldn't get encoded
|
||||
name.addFamilyElement().setValue(null).addExtension(new Extension("http://foo", new StringType("FOOEXT3")));
|
||||
name.setId("nameid");
|
||||
|
||||
String output = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(p);
|
||||
ourLog.info(output);
|
||||
|
||||
output = ourCtx.newXmlParser().setPrettyPrint(false).encodeResourceToString(p);
|
||||
String expected = "<Patient xmlns=\"http://hl7.org/fhir\"><id value=\"patid\"/><name id=\"nameid\"><family id=\"f0\"><extension url=\"http://foo\"><valueString value=\"FOOEXT0\"/></extension></family><family id=\"f1\" value=\"V1\"><extension id=\"ext1id\" url=\"http://foo\"><valueString value=\"FOOEXT1\"/></extension></family><family><extension url=\"http://foo\"><valueString value=\"FOOEXT3\"/></extension></family></name></Patient>";
|
||||
assertEquals(expected, output);
|
||||
|
||||
p = ourCtx.newXmlParser().parseResource(Patient.class, output);
|
||||
assertEquals("patid", p.getIdElement().getIdPart());
|
||||
|
||||
name = p.getName().get(0);
|
||||
assertEquals("nameid", name.getId());
|
||||
assertEquals(3, name.getFamily().size());
|
||||
|
||||
assertEquals(null, name.getFamily().get(0).getValue());
|
||||
assertEquals("V1", name.getFamily().get(1).getValue());
|
||||
assertEquals(null, name.getFamily().get(2).getValue());
|
||||
|
||||
assertEquals("f0", name.getFamily().get(0).getId());
|
||||
assertEquals("f1", name.getFamily().get(1).getId());
|
||||
assertEquals(null, name.getFamily().get(2).getId());
|
||||
|
||||
assertEquals(1, name.getFamily().get(0).getExtension().size());
|
||||
assertEquals("http://foo", name.getFamily().get(0).getExtension().get(0).getUrl());
|
||||
assertEquals("FOOEXT0", ((StringType)name.getFamily().get(0).getExtension().get(0).getValue()).getValue());
|
||||
assertEquals(null, name.getFamily().get(0).getExtension().get(0).getId());
|
||||
|
||||
assertEquals(1, name.getFamily().get(1).getExtension().size());
|
||||
assertEquals("http://foo", name.getFamily().get(1).getExtension().get(0).getUrl());
|
||||
assertEquals("FOOEXT1", ((StringType)name.getFamily().get(1).getExtension().get(0).getValue()).getValue());
|
||||
assertEquals("ext1id", name.getFamily().get(1).getExtension().get(0).getId());
|
||||
|
||||
assertEquals(1, name.getFamily().get(2).getExtension().size());
|
||||
assertEquals("http://foo", name.getFamily().get(2).getExtension().get(0).getUrl());
|
||||
assertEquals("FOOEXT3", ((StringType)name.getFamily().get(2).getExtension().get(0).getValue()).getValue());
|
||||
assertEquals(null, name.getFamily().get(2).getExtension().get(0).getId());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for #233
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
{
|
||||
"resourceType": "Patient",
|
||||
"identifier": [{
|
||||
"period": {"start": "2001-05-06"},
|
||||
"assigner": {"display": "Acme\u202fHealthcare"},
|
||||
"use": "usual",
|
||||
"system": "urn:oid:1.2.36.146.595.217.0.1",
|
||||
"value": "12345"
|
||||
}],
|
||||
|
||||
"_active": {"extension": [{
|
||||
"url": "http://example.org/fhir/StructureDefinition/recordStatus",
|
||||
"valueCode": "archived"
|
||||
}]},
|
||||
"name": [
|
||||
{
|
||||
"given": [
|
||||
"Peter",
|
||||
"James"
|
||||
],
|
||||
"use": "official",
|
||||
"family": ["Chalmers"]
|
||||
},
|
||||
{
|
||||
"given": ["Jim"],
|
||||
"use": "usual"
|
||||
}
|
||||
],
|
||||
"extension": [
|
||||
{
|
||||
"url": "http://example.org/fhir/StructureDefinition/patientAvatar",
|
||||
"valueReference": {
|
||||
"reference": "#pic1",
|
||||
"display": "Duck image"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "http://example.org/fhir/StructureDefinition/complexExtensionExample",
|
||||
"extension": [
|
||||
{
|
||||
"url": "nestedA",
|
||||
"valueCoding": {
|
||||
"system": "http://demo.org/id/4",
|
||||
"code": "AB45",
|
||||
"extension": [
|
||||
{
|
||||
"url": "http://example.org/fhir/StructureDefinition/extraforcodingWithExt",
|
||||
"extension": [{
|
||||
"url": "extra1",
|
||||
"valueString": "extra info"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"url": "http://example.org/fhir/StructureDefinition/extraforcodingWithValue",
|
||||
"valueInteger": 45
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "nestedB",
|
||||
"id": "q4",
|
||||
"extension": [{
|
||||
"url": "nestedB1",
|
||||
"valueString": "hello"
|
||||
}]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"modifierExtension": [
|
||||
{
|
||||
"url": "http://example.org/fhir/StructureDefinition/pi",
|
||||
"valueDecimal": 3.141592653589793
|
||||
},
|
||||
{
|
||||
"url": "http://example.org/fhir/StructureDefinition/avogadro",
|
||||
"valueDecimal": 6.0221416246424E23
|
||||
}
|
||||
],
|
||||
"gender": "male",
|
||||
"birthDate": "1974-12",
|
||||
"deceasedBoolean": true,
|
||||
"address": [{
|
||||
"use": "home",
|
||||
"line": ["534 Erewhon St"],
|
||||
"city": "PleasantVille",
|
||||
"state": "Vic",
|
||||
"postalCode": "3999"
|
||||
}],
|
||||
"maritalStatus": {
|
||||
"coding": [{
|
||||
"system": "http://hl7.org/fhir/v3/NullFlavor",
|
||||
"code": "UNK",
|
||||
"display": "unknown"
|
||||
}]
|
||||
},
|
||||
"multipleBirthInteger": 3,
|
||||
"text": {
|
||||
"status": "generated",
|
||||
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">\n <table>\n <tbody>\n <tr>\n <td>Name<\/td>\n <td>Peter James <b>Chalmers<\/b> ("Jim")<\/td>\n <\/tr>\n <tr>\n <td>Address<\/td>\n <td>534 Erewhon, Pleasantville, Vic, 3999<\/td>\n <\/tr>\n <tr>\n <td>Contacts<\/td>\n <td>Home: unknown. Work: (03) 5555 6473<\/td>\n <\/tr>\n <tr>\n <td>Id<\/td>\n <td>MRN: 12345 (Acme Healthcare)<\/td>\n <\/tr>\n <\/tbody>\n <\/table>\n <\/div>"
|
||||
},
|
||||
"contained": [
|
||||
{
|
||||
"resourceType": "Binary",
|
||||
"id": "pic1",
|
||||
"contentType": "image/gif",
|
||||
"content": "R0lGODlhEwARAPcAAAAAAAAA/+9aAO+1AP/WAP/eAP/eCP/eEP/eGP/nAP/nCP/nEP/nIf/nKf/nUv/nWv/vAP/vCP/vEP/vGP/vIf/vKf/vMf/vOf/vWv/vY//va//vjP/3c//3lP/3nP//tf//vf///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////yH5BAEAAAEALAAAAAATABEAAAi+AAMIDDCgYMGBCBMSvMCQ4QCFCQcwDBGCA4cLDyEGECDxAoAQHjxwyKhQAMeGIUOSJJjRpIAGDS5wCDly4AALFlYOgHlBwwOSNydM0AmzwYGjBi8IHWoTgQYORg8QIGDAwAKhESI8HIDgwQaRDI1WXXAhK9MBBzZ8/XDxQoUFZC9IiCBh6wEHGz6IbNuwQoSpWxEgyLCXL8O/gAnylNlW6AUEBRIL7Og3KwQIiCXb9HsZQoIEUzUjNEiaNMKAAAA7"
|
||||
},
|
||||
{
|
||||
"resourceType": "Organization",
|
||||
"id": "org3141",
|
||||
"text": {
|
||||
"status": "generated",
|
||||
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">\n <p>Good Health Clinic<\/p>\n <\/div>"
|
||||
},
|
||||
"identifier": [{
|
||||
"system": "urn:ietf:rfc:3986",
|
||||
"value": "2.16.840.1.113883.19.5"
|
||||
}],
|
||||
"name": "Good Health Clinic"
|
||||
}
|
||||
],
|
||||
"contact": [{
|
||||
"name": {
|
||||
"family": [
|
||||
null,
|
||||
"du",
|
||||
null,
|
||||
"Marché",
|
||||
null
|
||||
],
|
||||
"_family": [
|
||||
{"extension": [{
|
||||
"url": "http://example.org/fhir/StructureDefinition/nullFlavor",
|
||||
"valueCode": "ASKU"
|
||||
}]},
|
||||
{
|
||||
"id": "a2",
|
||||
"extension": [{
|
||||
"url": "http://example.org/fhir/StructureDefinition/qualifier",
|
||||
"valueCode": "VV"
|
||||
}]
|
||||
},
|
||||
{"extension": [{
|
||||
"url": "http://hl7.org/fhir/StructureDefinitioniso-21090#nullFlavor",
|
||||
"valueCode": "ASKU"
|
||||
}]},
|
||||
null,
|
||||
{"extension": [{
|
||||
"url": "http://hl7.org/fhir/StructureDefinition/nullFlavor",
|
||||
"valueCode": "ASKU"
|
||||
}]}
|
||||
],
|
||||
"_given": [
|
||||
null,
|
||||
{
|
||||
"id": "a3",
|
||||
"extension": [{
|
||||
"url": "http://hl7.org/fhir/StructureDefinition/qualifier",
|
||||
"valueCode": "MID"
|
||||
}]
|
||||
},
|
||||
null
|
||||
],
|
||||
"given": [
|
||||
"Bénédicte",
|
||||
"Denise",
|
||||
"Marie"
|
||||
]
|
||||
},
|
||||
"relationship": [{"coding": [{
|
||||
"system": "http://hl7.org/fhir/patient-contact-relationship",
|
||||
"code": "partner"
|
||||
}]}],
|
||||
"telecom": [{
|
||||
"system": "phone",
|
||||
"value": "+33 (237) 998327"
|
||||
}]
|
||||
}],
|
||||
"careProvider": [{"reference": "#org3141"}],
|
||||
"telecom": [
|
||||
{"use": "home"},
|
||||
{
|
||||
"system": "phone",
|
||||
"value": "(03) 5555 6473",
|
||||
"use": "work"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -416,6 +416,12 @@
|
|||
In server implementations, the Bundle.entry.fullUrl was not getting correctly
|
||||
populated on Hl7OrgDstu2 servers. Thanks to Christian Ohr for reporting!
|
||||
</action>
|
||||
<action type="fix" issue="335">
|
||||
Ensure that element IDs within resources (i.e. IDs on elements other than the
|
||||
resource itself) get serialized and parsed correctly. Previously, these didn't get
|
||||
serialized in a bunch of circumstances. Thanks to Vadim Peretokin for reporting
|
||||
and providing test cases!
|
||||
</action>
|
||||
</release>
|
||||
<release version="1.4" date="2016-02-04">
|
||||
<action type="add">
|
||||
|
|
Loading…
Reference in New Issue