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

Eliminate warnings for missing fields #1656

Closed
wants to merge 30 commits into from

Conversation

jbiskie
Copy link
Contributor

@jbiskie jbiskie commented Dec 12, 2024

Description

This PR updates and/or removes unnecessary fields in our FHIR mappings that were causing warnings when sending messages.

Issue

#940

When an extension contains a URL but no value of any type, the message "Resource is missing required element: value" is printed in the log.

There were 3 "value-less" extensions remaining that were producing these warnings.

  1. Patient identifier type code CX-5 (PID-3.5 in the v2 message) - transform: RemovePatientIdentifiers
  2. Patient name type code XPN-7 (PID-5.7 in the v2 message) - transform: RemovePatientNameTypeCode
  3. Observation request OBR-16 (occurs only when ORC-12 is blank - transform: CopyOrcOrderProviderToObrOrderProvider

This PR ensures that the "value-less" extensions do not get added during the TI transforms and does some additional cleanup of the transform output to ensure that the values being cleared by the transforms no longer exist in other places in the affected resource.

See the Areas of Concern comment in the issue for more details.

Testing instructions

  • Run a sample CA message with empty ORC-12 and OBR-16 through RS and TI end to end (such as CA examples 7, 19, or 20). Review the transformed fhir and final HL7.
  • The transformed fhir should have no extensions without a value (specifically CX.5, XPN.7, and OBR.16)
  • There should be no change in the final HL7

Checklist

  • I have added tests to cover my changes

Copy link

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Possible Bug
The method getObr16Extension might return null, which is not handled in getObr16ExtensionPractitioner. This could lead to a NullPointerException when calling obr16Extension.value.

Code Improvement
The method removePID3_5Value could be optimized by checking if the extension exists before attempting to remove it, which would avoid unnecessary method calls and potential NullPointerExceptions.

Copy link

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Score
Possible issue
Add null check for obrExtension to prevent potential NullPointerException

Ensure that the getObr16Extension method handles the possibility of obrExtension
being null to avoid potential NullPointerException when calling getExtensionByUrl.

etor/src/test/groovy/gov/hhs/cdc/trustedintermediary/etor/ruleengine/transformation/custom/CopyOrcOrderProviderToObrOrderProviderTest.groovy [240-243]

 Extension getObr16Extension(serviceRequest) {
     def obrExtension =  serviceRequest.getExtensionByUrl(HapiHelper.EXTENSION_OBR_URL)
+    if (obrExtension == null) return null
     def obr16Extension = obrExtension.getExtensionByUrl(HapiHelper.EXTENSION_OBR16_DATA_TYPE.toString())
     return obr16Extension
 }
Suggestion importance[1-10]: 8

Why: Adding a null check for obrExtension is crucial to prevent runtime exceptions when the extension is not present, which enhances the robustness of the method.

8
Add null check for organization to prevent NullPointerException

Check if organization is null after retrieving it in getPID3_4Identifier to avoid
NullPointerException when calling getResource.

shared/src/main/java/gov/hhs/cdc/trustedintermediary/external/hapi/HapiHelper.java [265-274]

 public static Identifier getPID3_4Identifier(Bundle bundle) {
     Identifier identifier = getPID3Identifier(bundle);
     if (identifier == null) {
         return null;
     }
     Organization organization = (Organization) identifier.getAssigner().getResource();
+    if (organization == null) {
+        return null;
+    }
     return organization.getIdentifierFirstRep();
 }
Suggestion importance[1-10]: 8

Why: This suggestion correctly adds a null check for organization to avoid NullPointerException when the organization is not present, which is a critical improvement for error handling.

8
Ensure patientIdentifier is properly checked for null and necessary conditions before usage

Add a null check for patientIdentifier before accessing its methods in
removePID3_5Value to prevent NullPointerException.

shared/src/main/java/gov/hhs/cdc/trustedintermediary/external/hapi/HapiHelper.java [294-297]

 public static void removePID3_5Value(Identifier patientIdentifier) {
-    if (patientIdentifier == null) {
+    if (patientIdentifier == null || !patientIdentifier.hasExtension(HapiHelper.EXTENSION_CX_IDENTIFIER_URL)) {
         return;
     }
     ...
 }
Suggestion importance[1-10]: 7

Why: The suggestion correctly identifies the need for additional null checks to prevent potential NullPointerException, which improves the method's safety and reliability.

7
Add checks to ensure the practitioner reference is valid before setting it

Ensure that setOBR16WithPractitioner checks if practitionerRole.getPractitioner()
has a valid reference before setting the value to avoid setting invalid data.

shared/src/main/java/gov/hhs/cdc/trustedintermediary/external/hapi/HapiHelper.java [543-553]

 public static void setOBR16WithPractitioner(
         Extension obrExtension, PractitionerRole practitionerRole) {
-    if (practitionerRole == null || !practitionerRole.getPractitioner().hasReference()) {
+    if (practitionerRole == null || !practitionerRole.getPractitioner().hasReference() || practitionerRole.getPractitioner().getReference().isEmpty()) {
         return;
     }
     ...
 }
Suggestion importance[1-10]: 6

Why: The suggestion enhances the method by ensuring that the practitioner reference is valid before setting it, which prevents the setting of invalid data and improves data integrity.

6

@JeremyIR JeremyIR requested a review from basiliskus December 13, 2024 20:55
@jbiskie jbiskie marked this pull request as ready for review December 13, 2024 21:18
HapiHelper.setPID3_4Value(bundle, ""); // remove PID.3-4
HapiHelper.setPID3_5Value(bundle, ""); // remove PID.3-5

Identifier patientIdentifier = HapiHelper.getPID3Identifier(bundle);
Copy link
Contributor

@basiliskus basiliskus Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can lines 20 to 24 be extracted to HapiHelper.setPID3_4Value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored.

// 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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just want to confirm that RS is not adding a value in PID-5.7 if we completely remove it instead of setting it to null

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. We noted the same behavior as the old comments indicated initially. We also need to null patient name use so ReportStream doesn't do a secondary mapping. I went ahead and added a link in the PR description to some comments in the task.

@@ -235,18 +237,18 @@ class CopyOrcOrderProviderToObrOrderProviderTest extends Specification{
assert codingSystem == null || codingSystem[0]?.code == expectedIdentifierTypeCode
}

Extension getObr16Extension(serviceRequest) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be useful to have getObr16Extension and some of the functions in this test in HapiHelper to be reused?

Copy link
Contributor Author

@jbiskie jbiskie Dec 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored the OBR-16 and ORC-12 methods into HapiHelper

@jbiskie jbiskie requested a review from basiliskus December 18, 2024 16:29
Copy link
Contributor

@basiliskus basiliskus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!

saquino0827 and others added 11 commits December 18, 2024 10:11
… can default to leaving it as a config change per user environment

Co-authored-by: Sylvie <sschuresko@flexion.us>
Co-authored-by: GilmoreA6 <james.gilmore@agile6.com>
Co-authored-by: pluckyswan <96704946+pluckyswan@users.noreply.github.com>
- template update to rename variables
- README update to reference where local set up of RS and TI are
- update local variables to be lower case
* comment to start branch

* getFieldsAnnotatedWithInstance helper method

* todo comment deleted

* injectIntoField overloaded method

* injectIntoNonSingleton

* access modifier protected to public

* revert access modifier change

* changes:
added logger to HapiFhirResource in order to test a non-singleton class
created HapiFhirResourceTest in order to test the changes to HapiFhirResource

* Added implementors unit test to ApplicationContextTest

* Minor refactoring on some AppContext injection methods

* Make the skip flag on TestApplicationContext switchable from the test classes

* Update ApplicationContext.java

Remove unreachable if statement

* Update TestApplicationContext.groovy

Add additional line in coverage

* Update TestApplicationContext.groovy

Remove parameter from injectRegisteredImplementations

* added unit tests to cover new code

* Update ApplicationContextTest.groovy

Added test case for unsupported injection classes

* Update ApplicationContext.java

Print an error message if the class implementation is not found

* use return instead of System.err

* refactoring - dry

* thown(NullPointerException) -> noExceptionThrown()

* added comments to indicate changes that will be deleted

* deleted commented out code

* reinstated comments for test case

* deleted test changes:
in HapiFhirResource
and deleted file HapifhirResourceTest.groovy

---------

Co-authored-by: Luis Pabon <turkeyfried@gmail.com>
Co-authored-by: Luis Pabon <luis.pabon@agile6.com>
…lue, refactor PID-3.4 testing into discrete unit tests
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
@jorg3lopez jorg3lopez force-pushed the bug/940-eliminate-warnings-for-missing-fields branch from c996bb6 to cc2b9d6 Compare December 18, 2024 18:14
@jbiskie
Copy link
Contributor Author

jbiskie commented Dec 19, 2024

Closing this PR in favor of #1664 due to unsigned commits in the branch.

@jbiskie jbiskie closed this Dec 19, 2024
@jbiskie jbiskie deleted the bug/940-eliminate-warnings-for-missing-fields branch December 20, 2024 22:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants