Skip to content

Commit

Permalink
merge master
Browse files Browse the repository at this point in the history
  • Loading branch information
Ken Stevens committed Jan 10, 2025
2 parents 3e0fe33 + e34cbd3 commit 4c9a52e
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 3 deletions.
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
Expand Up @@ -21,13 +21,13 @@ <h5>Social History</h5>
<tbody>
<th:block th:each="entry : ${resource.entry}" th:object="${entry.getResource()}">
<th:block th:unless='*{getResourceType().name() == "Composition"}'>
<th:block th:with="extension=${entry.getResource().getExtensionByUrl('http://hl7.org/fhir/StructureDefinition/narrativeLink').getValue().getValue()}">
<tr th:id="${#strings.arraySplit(extension, '#')[1]}">
<th:block th:with="extension=${entry.getResource().getExtensionByUrl('http://hl7.org/fhir/StructureDefinition/narrativeLink')}">
<tr th:id="${extension != null} ? ${#strings.arraySplit(extension.getValue().getValue(), '#')[1]} : ''">
<td th:insert="~{IpsUtilityFragments :: codeableConcept (cc=*{getCode()},attr='display')}">Code</td>
<td th:insert="~{IpsUtilityFragments :: renderValue (value=*{getValue()})}">Result</td>
<td th:insert="~{IpsUtilityFragments :: renderValueUnit (value=*{getValue()})}">Unit</td>
<td th:insert="~{IpsUtilityFragments :: concat (list=*{getNote()},attr='text')}">Comments</td>
<td th:insert="~{IpsUtilityFragments :: renderEffective (effective=*{getEffective()})}">Date</td>
<td th:insert="~{IpsUtilityFragments :: renderTime (time=*{getEffective()})}">Date</td>
</tr>
</th:block>
</th:block>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
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.hl7.fhir.dstu3.model.Procedure;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;
Expand All @@ -24,5 +28,87 @@ 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));
bundle.addEntry().setResource(new Procedure().setCode(new CodeableConcept(new Coding("http://loinc.org", "789", ""))));

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"));
}
}

0 comments on commit 4c9a52e

Please sign in to comment.