mirror of
https://github.com/hapifhir/hapi-fhir.git
synced 2025-02-16 18:05:19 +00:00
Fix #113 - Handle contained resources with non-local IDs
This commit is contained in:
parent
c3877c1da9
commit
95d5503a9a
@ -20,7 +20,7 @@ package ca.uhn.fhir.parser;
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
@ -47,7 +47,6 @@ import org.hl7.fhir.instance.model.api.IReference;
|
||||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeDeclaredChildDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeChildChoiceDefinition;
|
||||
@ -62,6 +61,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
||||
|
||||
public abstract class BaseParser implements IParser {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseParser.class);
|
||||
private ContainedResources myContainedResources;
|
||||
private FhirContext myContext;
|
||||
private boolean mySuppressNarratives;
|
||||
@ -80,6 +80,9 @@ public abstract class BaseParser implements IParser {
|
||||
for (IResource next : containedResources) {
|
||||
String nextId = next.getId().getValue();
|
||||
if (StringUtils.isNotBlank(nextId)) {
|
||||
if (!nextId.startsWith("#")) {
|
||||
nextId = '#' + nextId;
|
||||
}
|
||||
allIds.add(nextId);
|
||||
if (existingIdToContainedResource == null) {
|
||||
existingIdToContainedResource = new HashMap<String, IBaseResource>();
|
||||
@ -119,7 +122,7 @@ public abstract class BaseParser implements IParser {
|
||||
if (existingIdToContainedResource != null) {
|
||||
IBaseResource potentialTarget = existingIdToContainedResource.remove(next.getReference().getValue());
|
||||
if (potentialTarget != null) {
|
||||
theContained.addContained(potentialTarget);
|
||||
theContained.addContained(next.getReference(), potentialTarget);
|
||||
containResourcesForEncoding(theContained, potentialTarget, theTarget);
|
||||
}
|
||||
}
|
||||
@ -387,6 +390,11 @@ public abstract class BaseParser implements IParser {
|
||||
myResources.add(theResource);
|
||||
}
|
||||
|
||||
public void addContained(IdDt theId, IBaseResource theResource) {
|
||||
myResourceToId.put(theResource, theId);
|
||||
myResources.add(theResource);
|
||||
}
|
||||
|
||||
public List<IBaseResource> getContainedResources() {
|
||||
return myResources;
|
||||
}
|
||||
|
@ -104,6 +104,10 @@ import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||
import ca.uhn.fhir.util.ElementUtil;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
|
||||
/**
|
||||
* This class is the FHIR JSON parser/encoder. Users should not interact with this
|
||||
* class directly, but should use {@link FhirContext#newJsonParser()} to get an instance.
|
||||
*/
|
||||
public class JsonParser extends BaseParser implements IParser {
|
||||
|
||||
private static final Set<String> BUNDLE_TEXTNODE_CHILDREN_DSTU1;
|
||||
|
@ -20,14 +20,15 @@ package ca.uhn.fhir.parser;
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
@ -49,8 +50,8 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.instance.model.IBase;
|
||||
import org.hl7.fhir.instance.model.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.IPrimitiveType;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBinary;
|
||||
import org.hl7.fhir.instance.model.api.IBaseDatatype;
|
||||
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
||||
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
|
||||
@ -91,7 +92,12 @@ import ca.uhn.fhir.util.NonPrettyPrintWriterWrapper;
|
||||
import ca.uhn.fhir.util.PrettyPrintWriterWrapper;
|
||||
import ca.uhn.fhir.util.XmlUtil;
|
||||
|
||||
/**
|
||||
* This class is the FHIR XML parser/encoder. Users should not interact with this
|
||||
* class directly, but should use {@link FhirContext#newXmlParser()} to get an instance.
|
||||
*/
|
||||
public class XmlParser extends BaseParser implements IParser {
|
||||
|
||||
static final String ATOM_NS = "http://www.w3.org/2005/Atom";
|
||||
static final String FHIR_NS = "http://hl7.org/fhir";
|
||||
static final String OPENSEARCH_NS = "http://a9.com/-/spec/opensearch/1.1/";
|
||||
|
@ -20,11 +20,14 @@ import org.junit.Test;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.Tag;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.CodingDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.ContainedDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.DurationDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.HumanNameDt;
|
||||
import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt;
|
||||
@ -32,6 +35,7 @@ import ca.uhn.fhir.model.dstu2.resource.AllergyIntolerance;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Binary;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Composition;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Encounter;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Medication;
|
||||
import ca.uhn.fhir.model.dstu2.resource.MedicationPrescription;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Organization;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Patient;
|
||||
@ -53,6 +57,160 @@ public class XmlParserTest {
|
||||
XMLUnit.setIgnoreWhitespace(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* See #113
|
||||
*/
|
||||
@Test
|
||||
public void testEncodeContainedResources() {
|
||||
|
||||
MedicationPrescription medicationPrescript = new MedicationPrescription();
|
||||
|
||||
String medId = "123";
|
||||
CodeableConceptDt codeDt = new CodeableConceptDt("urn:sys", "code1");
|
||||
|
||||
// Adding medication to Contained.
|
||||
Medication medResource = new Medication();
|
||||
medResource.setCode(codeDt);
|
||||
medResource.setId("#" + String.valueOf(medId));
|
||||
ArrayList<IResource> medResList = new ArrayList<IResource>();
|
||||
medResList.add(medResource);
|
||||
ContainedDt medContainedDt = new ContainedDt();
|
||||
medContainedDt.setContainedResources(medResList);
|
||||
medicationPrescript.setContained(medContainedDt);
|
||||
|
||||
// Medication reference. This should point to the contained resource.
|
||||
ResourceReferenceDt medRefDt = new ResourceReferenceDt("#" + medId);
|
||||
medRefDt.setDisplay("MedRef");
|
||||
medicationPrescript.setMedication(medRefDt);
|
||||
|
||||
IParser p = ourCtx.newXmlParser().setPrettyPrint(true);
|
||||
String encoded = p.encodeResourceToString(medicationPrescript);
|
||||
ourLog.info(encoded);
|
||||
|
||||
//@formatter:on
|
||||
assertThat(encoded, stringContainsInOrder(
|
||||
"<MedicationPrescription xmlns=\"http://hl7.org/fhir\">",
|
||||
"<contained>",
|
||||
"<Medication xmlns=\"http://hl7.org/fhir\">",
|
||||
"<id value=\"123\"/>",
|
||||
"<code>",
|
||||
"<coding>",
|
||||
"<system value=\"urn:sys\"/>",
|
||||
"<code value=\"code1\"/>",
|
||||
"</coding>",
|
||||
"</code>",
|
||||
"</Medication>",
|
||||
"</contained>",
|
||||
"<medication>",
|
||||
"<reference value=\"#123\"/>",
|
||||
"<display value=\"MedRef\"/>",
|
||||
"</medication>",
|
||||
"</MedicationPrescription>"));
|
||||
//@formatter:off
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* See #113
|
||||
*/
|
||||
@Test
|
||||
public void testEncodeContainedResourcesManualContainUsingNonLocalId() {
|
||||
|
||||
MedicationPrescription medicationPrescript = new MedicationPrescription();
|
||||
|
||||
String medId = "123";
|
||||
CodeableConceptDt codeDt = new CodeableConceptDt("urn:sys", "code1");
|
||||
|
||||
// Adding medication to Contained.
|
||||
Medication medResource = new Medication();
|
||||
medResource.setCode(codeDt);
|
||||
medResource.setId(String.valueOf(medId)); // ID does not start with '#'
|
||||
ArrayList<IResource> medResList = new ArrayList<IResource>();
|
||||
medResList.add(medResource);
|
||||
ContainedDt medContainedDt = new ContainedDt();
|
||||
medContainedDt.setContainedResources(medResList);
|
||||
medicationPrescript.setContained(medContainedDt);
|
||||
|
||||
// Medication reference. This should point to the contained resource.
|
||||
ResourceReferenceDt medRefDt = new ResourceReferenceDt("#" + medId);
|
||||
medRefDt.setDisplay("MedRef");
|
||||
medicationPrescript.setMedication(medRefDt);
|
||||
|
||||
IParser p = ourCtx.newXmlParser().setPrettyPrint(true);
|
||||
String encoded = p.encodeResourceToString(medicationPrescript);
|
||||
ourLog.info(encoded);
|
||||
|
||||
//@formatter:on
|
||||
assertThat(encoded, stringContainsInOrder(
|
||||
"<MedicationPrescription xmlns=\"http://hl7.org/fhir\">",
|
||||
"<contained>",
|
||||
"<Medication xmlns=\"http://hl7.org/fhir\">",
|
||||
"<id value=\"123\"/>",
|
||||
"<code>",
|
||||
"<coding>",
|
||||
"<system value=\"urn:sys\"/>",
|
||||
"<code value=\"code1\"/>",
|
||||
"</coding>",
|
||||
"</code>",
|
||||
"</Medication>",
|
||||
"</contained>",
|
||||
"<medication>",
|
||||
"<reference value=\"#123\"/>",
|
||||
"<display value=\"MedRef\"/>",
|
||||
"</medication>",
|
||||
"</MedicationPrescription>"));
|
||||
//@formatter:off
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* See #113
|
||||
*/
|
||||
@Test
|
||||
public void testEncodeContainedResourcesAutomatic() {
|
||||
|
||||
MedicationPrescription medicationPrescript = new MedicationPrescription();
|
||||
String nameDisp = "MedRef";
|
||||
CodeableConceptDt codeDt = new CodeableConceptDt("urn:sys", "code1");
|
||||
|
||||
// Adding medication to Contained.
|
||||
Medication medResource = new Medication();
|
||||
// No ID set
|
||||
medResource.setCode(codeDt);
|
||||
|
||||
// Medication reference. This should point to the contained resource.
|
||||
ResourceReferenceDt medRefDt = new ResourceReferenceDt();
|
||||
medRefDt.setDisplay(nameDisp);
|
||||
// Resource reference set, but no ID
|
||||
medRefDt.setResource(medResource);
|
||||
medicationPrescript.setMedication(medRefDt);
|
||||
|
||||
IParser p = ourCtx.newXmlParser().setPrettyPrint(true);
|
||||
String encoded = p.encodeResourceToString(medicationPrescript);
|
||||
ourLog.info(encoded);
|
||||
|
||||
//@formatter:on
|
||||
assertThat(encoded, stringContainsInOrder(
|
||||
"<MedicationPrescription xmlns=\"http://hl7.org/fhir\">",
|
||||
"<contained>",
|
||||
"<Medication xmlns=\"http://hl7.org/fhir\">",
|
||||
"<id value=\"1\"/>",
|
||||
"<code>",
|
||||
"<coding>",
|
||||
"<system value=\"urn:sys\"/>",
|
||||
"<code value=\"code1\"/>",
|
||||
"</coding>",
|
||||
"</code>",
|
||||
"</Medication>",
|
||||
"</contained>",
|
||||
"<medication>",
|
||||
"<reference value=\"#1\"/>",
|
||||
"<display value=\"MedRef\"/>",
|
||||
"</medication>",
|
||||
"</MedicationPrescription>"));
|
||||
//@formatter:off
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeAndParseSecurityLabels() {
|
||||
Patient p = new Patient();
|
||||
|
Loading…
x
Reference in New Issue
Block a user