CDCgov / prime-reportstream

ReportStream is a public intermediary tool for delivery of data between different parts of the healthcare ecosystem.
https://reportstream.cdc.gov
Creative Commons Zero v1.0 Universal
71 stars 40 forks source link

[BUG] FHIR transforms not working for FHIR array properties #15729

Open victor-chaparro opened 1 month ago

victor-chaparro commented 1 month ago

Describe the bug

FHIR to FHIR transforms are unable to modify or suppress elements inside FHIR array properties such as Patient.name.given

Impact on ReportStream

ReportStream is unable de-identify FHIR bundles using FHIR to FHIR transforms and the workaround is to de-identify them in kotlin code.

Steps to reproduce

  1. Apply the below transform on a FHIR bundle to suppress a patient's first name
    - name: pii-removal-given-name
    resource: 'Bundle.entry.resource.ofType(Patient).name'
    value: [ '""' ]
    bundleProperty: '%resource.given[0]'
  2. An exception is thrown saying the property doesn't exist

Dev notes

Inside FhirTransformer.kt I was able to make it work by making the following changes and needs to be updated for it work on every array property in a FHIR bundle.

  /**
     * Updates a list of [Base] setting a property named [propertyName] to the passed value
     *
     * @param elementsToUpdate the list of [Base] to update
     * @param propertyName the property to set on each element
     * @param value what the property will get set to
     */
    private fun setBundleProperty(
        elementsToUpdate: List<Base>,
        propertyName: String,
        value: Base,
    ) {
        elementsToUpdate.forEach { penultimateElement ->
            //Remove index from property so that FHIR HAPI library can find the property in the bundle
            val property = penultimateElement.getNamedProperty(propertyName.replace(Regex("\\[.*?\\]"), ""))
            val newValue = FhirBundleUtils.convertFhirType(value, value.fhirType(), property.typeCode, logger)
            //Check if propertyName contains an index and if it does use the index to update the value
            //SetProperty will append to the array by default
            if(propertyName.contains("[")){ //This If would need to be updated to accept a regex that only accepts digits inside the brackets. Because this would break when using transforms that use value[x] as the property
                val index : Int?= Regex("\\[(.*?)\\]").find(propertyName)?.groupValues?.get(1)?.toInt()
                penultimateElement.setPropertyIndex(property.toString(),index,newValue.copy())
            } else {
                penultimateElement.setProperty(propertyName, newValue.copy())
            }
        }
    }

    //This would have to be updated to make it work for every property that is an array
    private fun Base.setPropertyIndex(propertyName: String, index: Int?, value: Base) {
        when(this) {
            is HumanName -> {
                when(propertyName) {
                    "given" -> index?.let { this.given[index] = value as StringType}
                }
            }
        }
    }

Expected behavior

mkalish commented 2 weeks ago

This is actually a feature request covered here: https://github.com/CDCgov/prime-reportstream/issues/16052