Skip to content

Commit

Permalink
Fixing parser for contained resources
Browse files Browse the repository at this point in the history
  • Loading branch information
madduci committed Mar 5, 2025
1 parent 0cd9d70 commit edf7dd4
Show file tree
Hide file tree
Showing 11 changed files with 78 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ public void wereBack() {
myErrorHandler.containedResourceWithNoId(null);
} else {
if (!res.getId().isLocal()) {
res.setId(new IdDt('#' + res.getId().getIdPart()));
res.setId(new IdDt(res.getId().getIdPart()));
}
getPreResourceState().getContainedResources().put(res.getId().getValueAsString(), res);
}
Expand Down Expand Up @@ -439,7 +439,7 @@ public void wereBack() {
// need an ID to be referred to)
myErrorHandler.containedResourceWithNoId(null);
} else {
res.getIdElement().setValue('#' + res.getIdElement().getIdPart());
res.getIdElement().setValue(res.getIdElement().getIdPart());
getPreResourceState()
.getContainedResources()
.put(res.getIdElement().getValue(), res);
Expand Down Expand Up @@ -1238,7 +1238,8 @@ void weaveContainedResources() {
String ref = nextRef.getReferenceElement().getValue();
if (isNotBlank(ref)) {
if (ref.startsWith("#") && ref.length() > 1) {
IBaseResource target = myContainedResources.get(ref);
String refId = ref.substring(1);
IBaseResource target = myContainedResources.get(refId);
if (target != null) {
ourLog.debug("Resource contains local ref {}", ref);
nextRef.setResource(target);
Expand Down Expand Up @@ -1285,7 +1286,7 @@ public void wereBack() {
super.wereBack();

IResource nextResource = (IResource) getCurrentElement();
String version = ResourceMetadataKeyEnum.VERSION.get(nextResource);
String version = nextResource.getId().getVersionIdPart();
String resourceName = myContext.getResourceType(nextResource);
String bundleIdPart = nextResource.getId().getIdPart();
if (isNotBlank(bundleIdPart)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.ValidationResult;
import jakarta.persistence.EntityManager;

import java.util.Objects;

import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
Expand Down Expand Up @@ -195,6 +198,7 @@
import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy;
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.validation.instance.advisor.BasePolicyAdvisorForFullValidation;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order;
Expand Down Expand Up @@ -562,6 +566,7 @@ public abstract class BaseJpaR4Test extends BaseJpaTest implements ITestDataBuil
@Autowired
protected IJobCoordinator myJobCoordinator;

private IValidationPolicyAdvisor policyAdvisor;
@RegisterExtension
private final PreventDanglingInterceptorsExtension myPreventDanglingInterceptorsExtension = new PreventDanglingInterceptorsExtension(()-> myInterceptorRegistry);

Expand Down Expand Up @@ -1076,8 +1081,12 @@ public ReferenceValidationPolicy policyForReference(IResourceValidator validator

@Override
public IValidationPolicyAdvisor getPolicyAdvisor() {
return this;
}
if (Objects.isNull(policyAdvisor)) {
return new BasePolicyAdvisorForFullValidation(getReferencePolicy());
}

return policyAdvisor;
}

@Override
public IValidationPolicyAdvisor setPolicyAdvisor(IValidationPolicyAdvisor policyAdvisor) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ public void testEncodeAndParseContained() {

assertNotNull(patient.getManagingOrganization().getResource());
org = (Organization) patient.getManagingOrganization().getResource();
assertEquals("#" + organizationUuid, org.getIdElement().getValue());
assertEquals(organizationUuid, org.getIdElement().getValue());
assertEquals("Contained Test Organization", org.getName());

// And re-encode a second time
Expand Down Expand Up @@ -1324,11 +1324,11 @@ public void testEncodeContainedResources() {
// Adding medication to Contained.
Medication medResource = new Medication();
medResource.setCode(codeDt);
medResource.setId("#" + medId);
medResource.setId(medId);
medicationPrescript.getContained().add(medResource);

// Medication reference. This should point to the contained resource.
Reference medRefDt = new Reference("#" + medId);
Reference medRefDt = new Reference(medId);
medRefDt.setDisplay("MedRef");
medicationPrescript.setMedication(medRefDt);

Expand All @@ -1339,7 +1339,7 @@ public void testEncodeContainedResources() {
// @formatter:on
assertThat(encoded).
contains("<MedicationRequest 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>", "<medicationReference>", "<reference value=\"#123\"/>",
"<system value=\"urn:sys\"/>", "<code value=\"code1\"/>", "</coding>", "</code>", "</Medication>", "</contained>", "<medicationReference>", "<reference value=\"123\"/>",
"<display value=\"MedRef\"/>", "</medicationReference>", "</MedicationRequest>");

}
Expand Down Expand Up @@ -1836,45 +1836,6 @@ public void testEncodeNarrativeSuppressed() {
assertThat(encoded).contains("maritalStatus");
}

@Test
public void testEncodeNonContained() {
// Create an organization
Organization org = new Organization();
org.setId("Organization/65546");
org.getNameElement().setValue("Contained Test Organization");

// Create a patient
Patient patient = new Patient();
patient.setId("Patient/1333");
patient.addIdentifier().setSystem("urn:mrns").setValue("253345");
patient.getManagingOrganization().setResource(org);

// Create a list containing both resources. In a server method, you might just
// return this list, but here we will create a bundle to encode.
List<IBaseResource> resources = new ArrayList<IBaseResource>();
resources.add(org);
resources.add(patient);

// Create a bundle with both
Bundle b = new Bundle();
b.addEntry().setResource(org);
b.addEntry().setResource(patient);

// Encode the buntdle
String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(b);
ourLog.info(encoded);
assertThat(encoded).doesNotContain("<contained>");
assertThat(encoded).contains("<Organization", "<id value=\"65546\"/>", "</Organization>");
assertThat(encoded).contains("<reference value=\"Organization/65546\"/>");
assertThat(encoded).contains("<Patient", "<id value=\"1333\"/>", "</Patient>");

encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(patient);
ourLog.info(encoded);
assertThat(encoded).doesNotContain("<contained>");
assertThat(encoded).contains("<reference value=\"Organization/65546\"/>");

}

/**
* See #312
*/
Expand Down Expand Up @@ -2055,17 +2016,17 @@ public void testEncodeWithContained() {

// Will be added by reference
Patient p = new Patient();
p.setId("#" + "1000");
p.setId("1000");
contained.add(p);

// Will be added by direct resource object
Location l = new Location();
l.setId("#" + "1001");
l.setId("1001");
contained.add(l);

// Will not be referred to (and therefore shouldn't appear in output)
Location l2 = new Location();
l2.setId("#1002");
l2.setId("1002");
contained.add(l2);

Appointment appointment = new Appointment();
Expand Down Expand Up @@ -3084,7 +3045,7 @@ public void testParseContainedBinaryResource() {

String encoded = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(manifest);
ourLog.info(encoded);
assertThat(encoded).contains("contained>", "<Binary", "</contained>");
assertThat(encoded).contains("<contained>", "<Binary", "</contained>");

DocumentManifest actual = ourCtx.newXmlParser().parseResource(DocumentManifest.class, encoded);
assertThat(actual.getContained()).hasSize(1);
Expand Down Expand Up @@ -3410,10 +3371,10 @@ public void testParseWovenContainedResources() throws IOException {

DiagnosticReport resource = (DiagnosticReport) bundle.getEntry().get(0).getResource();
Observation obs = (Observation) resource.getResult().get(1).getResource();
assertEquals("#2", obs.getId());
assertEquals("2", obs.getId());
Reference performerFirstRep = obs.getPerformerFirstRep();
Practitioner performer = (Practitioner) performerFirstRep.getResource();
assertEquals("#3", performer.getId());
assertEquals("3", performer.getId());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -413,8 +414,14 @@ public StructureDefinition fetchTypeDefinition(String theTypeName) {
}

@Override
public List<StructureDefinition> fetchTypeDefinitions(String s) {
return List.of(fetchTypeDefinition(s));
public List<StructureDefinition> fetchTypeDefinitions(String input) {
List<StructureDefinition> types = new ArrayList<>();
for (StructureDefinition sd : allStructures()) {
if (input.equals(sd.getTypeTail())) {
types.add(sd);
}
}
return types;
}

@Override
Expand Down Expand Up @@ -461,7 +468,11 @@ public <T extends org.hl7.fhir.r4.model.Resource> T fetchResourceWithException(C

@Override
public <T extends Resource> List<T> fetchResourcesByType(Class<T> aClass) {
return List.of();
List<T> res = new ArrayList<>();
if (aClass == StructureDefinition.class) {
res.addAll((Collection<? extends T>) getStructures());
}
return res;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ca.uhn.fhir.narrative;

import ca.uhn.fhir.context.FhirContext;
import org.hl7.fhir.r4.model.Meta;
import org.hl7.fhir.r4.model.Practitioner;
import org.hl7.fhir.r4.model.Quantity;
import org.hl7.fhir.r4.model.StringType;
Expand Down Expand Up @@ -49,6 +50,7 @@ public void testCustomType() {
myCtx.setNarrativeGenerator(null);

CustomPatient patient = new CustomPatient();
patient.setMeta(new Meta().addProfile("http://custom_patient"));
patient.setActive(true);
FavouritePizzaExtension parentExtension = new FavouritePizzaExtension();
parentExtension.setToppings(new StringType("Mushrooms, Onions"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1093,7 +1093,7 @@ public void testEncodeResourceWithMixedManualAndAutomaticContainedResourcesLocal
Observation obs = new Observation();

Patient pt = new Patient();
pt.setId("#1");
pt.setId("1");
pt.addName().setFamily("FAM");
obs.getSubject().setReference("#1");
obs.getContained().add(pt);
Expand All @@ -1106,8 +1106,8 @@ public void testEncodeResourceWithMixedManualAndAutomaticContainedResourcesLocal
ourLog.info(encoded);

obs = ourCtx.newJsonParser().parseResource(Observation.class, encoded);
assertEquals("#1", obs.getContained().get(0).getId());
assertEquals(enc.getId(), obs.getContained().get(1).getId());
assertEquals("1", obs.getContained().get(0).getId());
assertEquals(enc.getId(), "#" + obs.getContained().get(1).getId());

pt = (Patient) obs.getSubject().getResource();
assertEquals("FAM", pt.getNameFirstRep().getFamily());
Expand All @@ -1126,7 +1126,7 @@ public void testEncodeResourceWithMixedManualAndAutomaticContainedResourcesLocal
obs.getSubject().setResource(pt);

Encounter enc = new Encounter();
enc.setId("#1");
enc.setId("1");
enc.setStatus(Encounter.EncounterStatus.ARRIVED);
obs.getEncounter().setReference("#1");
obs.getContained().add(enc);
Expand All @@ -1135,8 +1135,8 @@ public void testEncodeResourceWithMixedManualAndAutomaticContainedResourcesLocal
ourLog.info(encoded);

obs = ourCtx.newJsonParser().parseResource(Observation.class, encoded);
assertEquals("#1", obs.getContained().get(0).getId());
assertEquals(pt.getId(), obs.getContained().get(1).getId());
assertEquals("1", obs.getContained().get(0).getId());
assertEquals(pt.getId(), "#" + obs.getContained().get(1).getId());

pt = (Patient) obs.getSubject().getResource();
assertEquals("FAM", pt.getNameFirstRep().getFamily());
Expand All @@ -1162,8 +1162,8 @@ public void testEncodeResourceWithMixedManualAndAutomaticContainedResourcesLocal
ourLog.info(encoded);
mr = ourCtx.newJsonParser().parseResource(MedicationRequest.class, encoded);

assertEquals(pract.getId(), mr.getContained().get(0).getId());
assertEquals(med.getId(), mr.getContained().get(1).getId());
assertEquals(pract.getId(), "#" + mr.getContained().get(0).getId());
assertEquals(med.getId(), "#" + mr.getContained().get(1).getId());

}

Expand Down Expand Up @@ -1675,8 +1675,8 @@ public void testParseAndEncodePreservesContainedResourceOrder() {

ourLog.info("Input: {}", auditEvent);
AuditEvent ae = ourCtx.newJsonParser().parseResource(AuditEvent.class, auditEvent);
assertEquals("#A", ae.getContained().get(0).getId());
assertEquals("#B", ae.getContained().get(1).getId());
assertEquals("A", ae.getContained().get(0).getId());
assertEquals("B", ae.getContained().get(1).getId());
assertEquals("#B", ae.getEntity().get(0).getWhat().getReference());
assertEquals("#A", ae.getEntity().get(1).getWhat().getReference());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ public void testParseAndEncodePreservesContainedResourceOrder() {

ourLog.info("Input: {}", auditEvent);
AuditEvent ae = ourCtx.newXmlParser().parseResource(AuditEvent.class, auditEvent);
assertEquals("#A", ae.getContained().get(0).getId());
assertEquals("#B", ae.getContained().get(1).getId());
assertEquals("A", ae.getContained().get(0).getId());
assertEquals("B", ae.getContained().get(1).getId());
assertEquals("#B", ae.getEntity().get(0).getWhat().getReference());
assertEquals("#A", ae.getEntity().get(1).getWhat().getReference());

Expand Down
Loading

0 comments on commit edf7dd4

Please sign in to comment.