Skip to content

Commit

Permalink
Merge pull request #1664 from CDCgov/bug/940-commit-fix-eliminate-war…
Browse files Browse the repository at this point in the history
…nings-for-missing-fields

Eliminate warnings for missing fields (fix unsigned commits)
  • Loading branch information
jbiskie authored Dec 19, 2024
2 parents 5d991fe + b23b0ae commit d257103
Show file tree
Hide file tree
Showing 8 changed files with 511 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,8 @@ public void transform(HealthData<?> resource, Map<String, Object> args) {
return;
}

// Extract or create the OBR-16 extension from the ServiceRequest
Extension obrExtension =
HapiHelper.ensureExtensionExists(serviceRequest, HapiHelper.EXTENSION_OBR_URL);

// Extract or create the OBR-16 data type extension
Extension obr16Extension =
HapiHelper.ensureSubExtensionExists(
obrExtension, HapiHelper.EXTENSION_OBR16_DATA_TYPE.toString());

// Set the ORC-12 Practitioner in the OBR-16 extension
HapiHelper.setOBR16WithPractitioner(obr16Extension, practitionerRole);
HapiHelper.setOBR16WithPractitioner(obrExtension, practitionerRole);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ public class RemovePatientIdentifiers implements CustomFhirTransformation {
@Override
public void transform(HealthData<?> resource, Map<String, Object> args) {
Bundle bundle = (Bundle) resource.getUnderlyingData();
HapiHelper.setPID3_4Value(bundle, ""); // remove PID.3-4
HapiHelper.setPID3_5Value(bundle, ""); // remove PID.3-5

HapiHelper.setPID3_4Value(bundle, null);
HapiHelper.removePID3_5Value(bundle);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ public class RemovePatientNameTypeCode implements CustomFhirTransformation {
@Override
public void transform(final HealthData<?> resource, final Map<String, Object> args) {
Bundle bundle = (Bundle) resource.getUnderlyingData();
// Need to set the value for extension to empty instead of removing the extension,
// otherwise RS will set its own value in its place
HapiHelper.setPID5_7ExtensionValue(bundle, null);
HapiHelper.removePID5_7Value(bundle);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import gov.hhs.cdc.trustedintermediary.external.hapi.HapiHelper
import gov.hhs.cdc.trustedintermediary.wrappers.MetricMetadata
import org.hl7.fhir.r4.model.Bundle
import org.hl7.fhir.r4.model.DiagnosticReport
import org.hl7.fhir.r4.model.Practitioner
import org.hl7.fhir.r4.model.Reference
import org.hl7.fhir.r4.model.ServiceRequest
import spock.lang.Specification

Expand Down Expand Up @@ -119,7 +117,7 @@ class CopyOrcOrderProviderToObrOrderProviderTest extends Specification{
evaluateOrc12Values(bundle, EXPECTED_NPI, EXPECTED_FIRST_NAME, EXPECTED_LAST_NAME, EXPECTED_NAME_TYPE_CODE, EXPECTED_IDENTIFIER_TYPE_CODE)

// OBR16 should not exist initially
def obr16Practitioner = getObr16ExtensionPractitioner(serviceRequest)
def obr16Practitioner = HapiHelper.getObr16ExtensionPractitioner(serviceRequest)
obr16Practitioner == null

when:
Expand Down Expand Up @@ -191,7 +189,7 @@ class CopyOrcOrderProviderToObrOrderProviderTest extends Specification{
}

void evaluateOrc12IsNull(Bundle bundle) {
assert getOrc12ExtensionPractitioner(bundle) == null
assert HapiHelper.getOrc12ExtensionPractitioner(bundle) == null
}

void evaluateOrc12Values(
Expand All @@ -201,7 +199,7 @@ class CopyOrcOrderProviderToObrOrderProviderTest extends Specification{
String expectedLastName,
String expectedNameTypeCode,
String expectedIdentifierTypeCode) {
def practitioner = getOrc12ExtensionPractitioner(bundle)
def practitioner = HapiHelper.getOrc12ExtensionPractitioner(bundle)
def xcnExtension = practitioner.getExtensionByUrl(PRACTITIONER_EXTENSION_URL)

assert practitioner.identifier[0]?.value == expectedNpi
Expand All @@ -214,7 +212,8 @@ class CopyOrcOrderProviderToObrOrderProviderTest extends Specification{
}

void evaluateObr16IsNull(ServiceRequest serviceRequest) {
assert getObr16ExtensionPractitioner(serviceRequest) == null
assert HapiHelper.getObr16Extension(serviceRequest) == null
assert HapiHelper.getObr16ExtensionPractitioner(serviceRequest) == null
}

void evaluateObr16Values(
Expand All @@ -224,7 +223,7 @@ class CopyOrcOrderProviderToObrOrderProviderTest extends Specification{
String expectedLastName,
String expectedNameTypeCode,
String expectedIdentifierTypeCode) {
def practitioner = getObr16ExtensionPractitioner(serviceRequest)
def practitioner = HapiHelper.getObr16ExtensionPractitioner(serviceRequest)
def xcnExtension = practitioner.getExtensionByUrl(PRACTITIONER_EXTENSION_URL)

assert practitioner.identifier[0]?.value == expectedNpi
Expand All @@ -234,40 +233,4 @@ class CopyOrcOrderProviderToObrOrderProviderTest extends Specification{
def codingSystem = practitioner.identifier[0]?.type?.coding
assert codingSystem == null || codingSystem[0]?.code == expectedIdentifierTypeCode
}

Practitioner getObr16ExtensionPractitioner (serviceRequest) {
def resource
try {
def extensionByUrl1 = serviceRequest.getExtensionByUrl(HapiHelper.EXTENSION_OBR_URL)
def extensionByUrl2 = extensionByUrl1.getExtensionByUrl(HapiHelper.EXTENSION_OBR16_DATA_TYPE.toString())
def value = extensionByUrl2.value
resource = value.getResource()
return resource
} catch(Exception ignored) {
resource = null
return resource
}
}

Practitioner getOrc12ExtensionPractitioner(Bundle bundle) {
def diagnosticReport = HapiHelper.getDiagnosticReport(bundle)
def serviceRequest = HapiHelper.getServiceRequest(diagnosticReport)

def orcExtension = serviceRequest.getExtensionByUrl(HapiHelper.EXTENSION_ORC_URL)
def orc12Extension = orcExtension.getExtensionByUrl(HapiHelper.EXTENSION_ORC12_URL)

if (orc12Extension == null) {
return null
}

def practitionerReference = (Reference) orc12Extension.getValue()
def practitionerUrl = practitionerReference.getReference()

for (Bundle.BundleEntryComponent entry : bundle.getEntry()) {
if (Objects.equals(entry.getFullUrl(), practitionerUrl) && entry.getResource() instanceof Practitioner)
return (Practitioner) entry.getResource()
}

return null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ class RemovePatientIdentifierTest extends Specification {

when:
transformClass.transform(fhirResource, null)
def actualPid3_4 = HapiFhirHelper.getPID3_4Value(bundle)
def actualPid3_5 = HapiFhirHelper.getPID3_5Value(bundle)

then:
def actualPid3_4 = HapiFhirHelper.getPID3_4Value(bundle)
def actualPid3_5 = HapiFhirHelper.getPID3_5Value(bundle)
actualPid3_4 == null || actualPid3_4.isEmpty()
actualPid3_5 == null || actualPid3_5.isEmpty()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,22 @@ class RemovePatientNameTypeCodeTest extends Specification {

def "remove PID.5-7 from Bundle"() {
given:
def fhirResource = ExamplesHelper.getExampleFhirResource("../CA/002_CA_ORU_R01_initial_translation.fhir")
def fhirResource = ExamplesHelper.getExampleFhirResource("../CA/007_CA_ORU_R01_CDPH_produced_UCSD2024-07-11-16-02-17-749_1_hl7_translation.fhir")
def bundle = fhirResource.getUnderlyingData() as Bundle
def pid5_7 = HapiFhirHelper.getPID5_7Value(bundle)
def pid5Extension = HapiHelper.getPID5Extension(bundle)
def patientName = HapiHelper.getPIDPatient(bundle).getNameFirstRep()
def patientNameUse = patientName.getUse()

expect:
pid5_7 != null
pid5Extension.getExtensionByUrl(HapiHelper.EXTENSION_XPN7_URL) != null
patientNameUse.toString() == "OFFICIAL"

when:
transformClass.transform(fhirResource, null)

then:
HapiFhirHelper.getPID5_7Value(bundle) == null
pid5Extension.getExtensionByUrl(HapiHelper.EXTENSION_XPN7_URL) == null
!patientName.hasUse()
}

def "don't throw exception if patient resource not present"() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.hl7.fhir.r4.model.Patient;
import org.hl7.fhir.r4.model.Practitioner;
import org.hl7.fhir.r4.model.PractitionerRole;
import org.hl7.fhir.r4.model.Reference;
import org.hl7.fhir.r4.model.Resource;
import org.hl7.fhir.r4.model.ServiceRequest;
import org.hl7.fhir.r4.model.StringType;
Expand Down Expand Up @@ -268,15 +269,27 @@ public static Identifier getPID3_4Identifier(Bundle bundle) {
return null;
}
Organization organization = (Organization) identifier.getAssigner().getResource();
if (organization == null) {
return null;
}
return organization.getIdentifierFirstRep();
}

public static void setPID3_4Value(Bundle bundle, String value) {
Identifier identifier = getPID3_4Identifier(bundle);
if (identifier == null) {
if (value == null) {
Identifier pid3Identifier = getPID3Identifier(bundle);
if (pid3Identifier == null) {
return;
}
pid3Identifier.setAssigner(null);
return;
}
identifier.setValue(value);

Identifier pid3_4Identifier = getPID3_4Identifier(bundle);
if (pid3_4Identifier == null) {
return;
}
pid3_4Identifier.setValue(value);
}

// PID-3.5 - Identifier Type Code
Expand All @@ -288,22 +301,61 @@ public static void setPID3_5Value(Bundle bundle, String value) {
setCX5Value(identifier, value);
}

public static void removePID3_5Value(Bundle bundle) {
Identifier patientIdentifier = getPID3Identifier(bundle);
if (patientIdentifier == null) {
return;
}

patientIdentifier.setType(null);

Extension cxExtension = patientIdentifier.getExtensionByUrl(EXTENSION_CX_IDENTIFIER_URL);
if (cxExtension == null) {
return;
}

if (cxExtension.hasExtension(EXTENSION_CX5_URL)) {
cxExtension.removeExtension(EXTENSION_CX5_URL);
}

// The cx-identifier extension can be removed if it has no more sub-extensions
if (cxExtension.getExtension().isEmpty()) {
patientIdentifier.removeExtension(EXTENSION_CX_IDENTIFIER_URL);
}
}

// PID-5 - Patient Name
public static Extension getPID5Extension(Bundle bundle) {
Patient patient = getPIDPatient(bundle);
if (patient == null) {
return null;
}
HumanName name = patient.getNameFirstRep();
return name.getExtensionByUrl(HapiHelper.EXTENSION_XPN_HUMAN_NAME_URL);
return name.getExtensionByUrl(EXTENSION_XPN_HUMAN_NAME_URL);
}

public static void setPID5_7ExtensionValue(Bundle bundle, String value) {
Extension extension = getPID5Extension(bundle);
if (extension != null && extension.hasExtension(HapiHelper.EXTENSION_XPN7_URL)) {
extension
.getExtensionByUrl(HapiHelper.EXTENSION_XPN7_URL)
.setValue(new StringType(value));
if (extension != null && extension.hasExtension(EXTENSION_XPN7_URL)) {
extension.getExtensionByUrl(EXTENSION_XPN7_URL).setValue(new StringType(value));
}
}

public static void removePID5_7Value(Bundle bundle) {
Patient patient = getPIDPatient(bundle);
if (patient == null) {
return;
}
HumanName patientName = patient.getNameFirstRep();
patientName.setUse(null);

Extension pid5Extension = getPID5Extension(bundle);
if (pid5Extension == null) {
return;
}
Extension xpn7Extension = pid5Extension.getExtensionByUrl(EXTENSION_XPN7_URL);
if (xpn7Extension != null) {
pid5Extension.removeExtension(EXTENSION_XPN7_URL);
}
}

Expand Down Expand Up @@ -499,17 +551,69 @@ public static String getOBR4_1Value(ServiceRequest serviceRequest) {
return getCWE1Value(cc.getCoding().get(0));
}

// OBR16 - Ordering Provider

// OBR16 -
// OBR-16 - Ordering Provider
public static void setOBR16WithPractitioner(
Extension obr16Extension, PractitionerRole practitionerRole) {
if (practitionerRole == null) {
Extension obrExtension, PractitionerRole practitionerRole) {
if (practitionerRole == null || !practitionerRole.getPractitioner().hasReference()) {
return;
}

Extension obr16Extension =
ensureSubExtensionExists(obrExtension, EXTENSION_OBR16_DATA_TYPE.toString());

obr16Extension.setValue(practitionerRole.getPractitioner());
}

public static Extension getObr16Extension(ServiceRequest serviceRequest) {
Extension obrExtension = serviceRequest.getExtensionByUrl(EXTENSION_OBR_URL);
if (obrExtension == null) {
return null;
}
return obrExtension.getExtensionByUrl(EXTENSION_OBR16_DATA_TYPE.toString());
}

public static Practitioner getObr16ExtensionPractitioner(ServiceRequest serviceRequest) {
Extension obr16Extension = getObr16Extension(serviceRequest);
if (obr16Extension == null || obr16Extension.getValue() == null) {
return null;
}

if (obr16Extension.getValue() instanceof Reference reference
&& reference.getResource() instanceof Practitioner practitioner) {
return practitioner;
}
return null;
}

// ORC-12 - Ordering Provider
public static Practitioner getOrc12ExtensionPractitioner(Bundle bundle) {
DiagnosticReport diagnosticReport = getDiagnosticReport(bundle);
if (diagnosticReport == null) return null;

ServiceRequest serviceRequest = getServiceRequest(diagnosticReport);
if (serviceRequest == null) return null;

Extension orcExtension = serviceRequest.getExtensionByUrl(EXTENSION_ORC_URL);
if (orcExtension == null) return null;

Extension orc12Extension = orcExtension.getExtensionByUrl(EXTENSION_ORC12_URL);
if (orc12Extension == null) return null;

Reference practitionerReference = (Reference) orc12Extension.getValue();
if (practitionerReference == null) return null;

String practitionerUrl = practitionerReference.getReference();
if (practitionerUrl == null) return null;

for (Bundle.BundleEntryComponent entry : bundle.getEntry()) {
if (Objects.equals(entry.getFullUrl(), practitionerUrl)
&& entry.getResource() instanceof Practitioner practitioner)
return practitioner;
}

return null;
}

/**
* Ensures that the extension exists for a given serviceRequest. If the extension does not
* exist, it will create it.
Expand Down Expand Up @@ -678,9 +782,9 @@ public static void removeHl7FieldIdentifier(List<Identifier> identifiers, String

public static String urlForCodeType(String code) {
return switch (code) {
case HapiHelper.LOINC_CODE -> HapiHelper.LOINC_URL;
case HapiHelper.PLT_CODE -> null;
default -> HapiHelper.LOCAL_CODE_URL;
case LOINC_CODE -> LOINC_URL;
case PLT_CODE -> null;
default -> LOCAL_CODE_URL;
};
}

Expand All @@ -695,22 +799,19 @@ public static String urlForCodeType(String code) {
*/
public static boolean hasDefinedCoding(
Coding coding, String codingExt, String codingSystemExt) {
var codingExtMatch =
hasMatchingCodingExtension(coding, HapiHelper.EXTENSION_CWE_CODING, codingExt);
var codingExtMatch = hasMatchingCodingExtension(coding, EXTENSION_CWE_CODING, codingExt);
var codingSystemExtMatch =
hasMatchingCodingExtension(
coding, HapiHelper.EXTENSION_CODING_SYSTEM, codingSystemExt);
hasMatchingCodingExtension(coding, EXTENSION_CODING_SYSTEM, codingSystemExt);
return codingExtMatch && codingSystemExtMatch;
}

private static boolean hasMatchingCodingExtension(
Coding coding, String extensionUrl, String valueToMatch) {
if (!HapiHelper.hasCodingExtensionWithUrl(coding, extensionUrl)) {
if (!hasCodingExtensionWithUrl(coding, extensionUrl)) {
return false;
}

var extensionValue =
HapiHelper.getCodingExtensionByUrl(coding, extensionUrl).getValue().toString();
var extensionValue = getCodingExtensionByUrl(coding, extensionUrl).getValue().toString();
return Objects.equals(valueToMatch, extensionValue);
}

Expand Down
Loading

0 comments on commit d257103

Please sign in to comment.