Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added new narrative generator utility method #6602

Merged
merged 3 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,17 @@
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.util.BundleUtil;
import ca.uhn.fhir.util.TerserUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseCoding;
import org.hl7.fhir.instance.model.api.IBaseResource;

import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;

/**
* An instance of this class is added to the Thymeleaf context as a variable with
Expand All @@ -52,4 +57,64 @@ public boolean bundleHasEntriesWithResourceType(IBaseBundle theBaseBundle, Strin
.filter(Objects::nonNull)
.anyMatch(t -> ctx.getResourceType(t).equals(theResourceType));
}

/**
* Returns if the bundle contains an entry resource whose `code` property contains a matching code system and code.
*
* @param theBundle the bundle to inspect
* @param theResourceType the resource type to look for
* @param theCodeSystem the code system to find
* @param theCode the code to find
* @return returns true if bundle has a resource that with matching code/code system
*/
public boolean bundleHasEntriesWithCode(
IBaseBundle theBundle, String theResourceType, String theCodeSystem, String theCode) {
FhirVersionEnum fhirVersionEnum = theBundle.getStructureFhirVersionEnum();
FhirContext ctx = FhirContext.forCached(fhirVersionEnum);

return getEntryResources(ctx, theBundle, theResourceType).anyMatch(t -> {
List<IBase> codeList = TerserUtil.getFieldByFhirPath(ctx, "code.coding", t);
return codeList.stream().anyMatch(m -> {
IBaseCoding coding = (IBaseCoding) m;
return StringUtils.equals(coding.getSystem(), theCodeSystem)
&& StringUtils.equals(coding.getCode(), theCode);
});
});
}

/**
* Gets a boolean indicating if at least one bundle entry resource's `code` property does NOT contain the
* code system/code specified.
*
* @param theBundle the bundle to inspect
* @param theResourceType the resource type to find
* @param theCodeSystem the code system to find
* @param theCode the code to find
* @return Returns true if one entry of resource type requested does not contain the specified code/system
*/
public boolean bundleHasEntriesWithoutCode(
IBaseBundle theBundle, String theResourceType, String theCodeSystem, String theCode) {

FhirVersionEnum fhirVersionEnum = theBundle.getStructureFhirVersionEnum();
FhirContext ctx = FhirContext.forCached(fhirVersionEnum);

return getEntryResources(ctx, theBundle, theResourceType).anyMatch(t -> {
List<IBase> codeList = TerserUtil.getFieldByFhirPath(ctx, "code.coding", t);
return codeList.stream().allMatch(m -> {
IBaseCoding coding = (IBaseCoding) m;
return !(StringUtils.equals(coding.getSystem(), theCodeSystem)
&& StringUtils.equals(coding.getCode(), theCode));
});
});
}

private Stream<IBaseResource> getEntryResources(
FhirContext theContext, IBaseBundle theBundle, String theResourceType) {
List<Pair<String, IBaseResource>> entryResources =
BundleUtil.getBundleEntryUrlsAndResources(theContext, theBundle);
return entryResources.stream()
.map(Pair::getValue)
.filter(Objects::nonNull)
.filter(t -> theContext.getResourceType(t).equals(theResourceType));
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package ca.uhn.fhir.narrative2;

import org.hl7.fhir.dstu3.model.Bundle;
import org.hl7.fhir.dstu3.model.CodeableConcept;
import org.hl7.fhir.dstu3.model.Coding;
import org.hl7.fhir.dstu3.model.Medication;
import org.hl7.fhir.dstu3.model.Observation;
import org.hl7.fhir.dstu3.model.Patient;
import org.junit.jupiter.api.Test;

Expand All @@ -24,5 +27,86 @@ public void testBundleHasEntriesWithResourceType_False() {
assertFalse(NarrativeGeneratorTemplateUtils.INSTANCE.bundleHasEntriesWithResourceType(bundle, "Patient"));
}

@Test
public void testResourcesHaveCodeValue_isTrue() {
Bundle bundle = new Bundle();
bundle.addEntry().setResource(new Observation().setCode(
new CodeableConcept(
new Coding("http://loinc.org", "123", ""))));
bundle.addEntry().setResource(new Observation().setCode(
new CodeableConcept(
new Coding("http://loinc.org", "456", ""))));

assertTrue(NarrativeGeneratorTemplateUtils.INSTANCE
.bundleHasEntriesWithCode(bundle, "Observation", "http://loinc.org", "123"));
}

@Test
public void testResourcesHaveCodeValue_isTrueWhenOneCodeMatches() {
Bundle bundle = new Bundle();
bundle.addEntry().setResource(new Observation().setCode(
new CodeableConcept()
.addCoding(new Coding("http://loinc.org", "abc", ""))
.addCoding(new Coding("http://loinc.org", "123", ""))
));
bundle.addEntry().setResource(new Observation().setCode(
new CodeableConcept(
new Coding("http://loinc.org", "456", ""))));

assertTrue(NarrativeGeneratorTemplateUtils.INSTANCE
.bundleHasEntriesWithCode(bundle, "Observation", "http://loinc.org", "123"));
}

@Test
public void testResourcesHaveCodeValue_isFalse() {
Bundle bundle = new Bundle();
bundle.addEntry().setResource(new Observation().setCode(
new CodeableConcept(
new Coding("http://loinc.org", "123", ""))));
bundle.addEntry().setResource(new Observation().setCode(
new CodeableConcept(
new Coding("http://loinc.org", "456", ""))));

assertFalse(NarrativeGeneratorTemplateUtils.INSTANCE
.bundleHasEntriesWithCode(bundle, "Observation", "http://loinc.org", "789"));
}

@Test
public void testResourcesHaveCodeValue_isFalseWhenNoResourcePresent() {
Bundle bundle = new Bundle();
bundle.addEntry().setResource(new Patient().setActive(true));
bundle.addEntry().setResource(new Medication().setIsBrand(true));

davidraeside marked this conversation as resolved.
Show resolved Hide resolved
assertFalse(NarrativeGeneratorTemplateUtils.INSTANCE
.bundleHasEntriesWithCode(bundle, "Observation", "http://loinc.org", "789"));
}

@Test
public void testResourcesDoNotHaveCodeValue_isTrue() {
Bundle bundle = new Bundle();
bundle.addEntry().setResource(new Observation().setCode(
new CodeableConcept(
new Coding("http://loinc.org", "123", ""))));
bundle.addEntry().setResource(new Observation().setCode(
new CodeableConcept(
new Coding("http://loinc.org", "456", ""))));

assertTrue(NarrativeGeneratorTemplateUtils.INSTANCE
.bundleHasEntriesWithoutCode(bundle, "Observation", "http://loinc.org", "456"));
}

@Test
public void testResourcesDoNotHaveCodeValue_isFalse() {
Bundle bundle = new Bundle();
bundle.addEntry().setResource(new Observation().setCode(
new CodeableConcept(
new Coding("http://loinc.org", "456", ""))));
bundle.addEntry().setResource(new Observation().setCode(
new CodeableConcept()
.addCoding(new Coding("http://loinc.org", "abc", ""))
.addCoding(new Coding("http://loinc.org", "456", ""))
));
assertFalse(NarrativeGeneratorTemplateUtils.INSTANCE
.bundleHasEntriesWithoutCode(bundle, "Observation", "http://loinc.org", "456"));
}
}
Loading