diff --git a/prime-router/build.gradle.kts b/prime-router/build.gradle.kts
index 90a5971f314..b64a5b7208e 100644
--- a/prime-router/build.gradle.kts
+++ b/prime-router/build.gradle.kts
@@ -858,6 +858,9 @@ dependencies {
// https://mvnrepository.com/artifact/ca.uhn.hapi.fhir/hapi-fhir-caching-caffeine
implementation("ca.uhn.hapi.fhir:hapi-fhir-caching-caffeine:7.2.2")
implementation("ca.uhn.hapi.fhir:hapi-fhir-client:7.2.2")
+ // pin
+ implementation("ca.uhn.hapi.fhir:org.hl7.fhir.utilities:6.3.24")
+ implementation("ca.uhn.hapi.fhir:org.hl7.fhir.r4:6.3.24")
implementation("ca.uhn.hapi:hapi-base:2.5.1")
implementation("ca.uhn.hapi:hapi-structures-v251:2.5.1")
implementation("ca.uhn.hapi:hapi-structures-v27:2.5.1")
diff --git a/prime-router/src/main/kotlin/cli/ProcessFhirCommands.kt b/prime-router/src/main/kotlin/cli/ProcessFhirCommands.kt
index 32321a12871..0b2d70a7149 100644
--- a/prime-router/src/main/kotlin/cli/ProcessFhirCommands.kt
+++ b/prime-router/src/main/kotlin/cli/ProcessFhirCommands.kt
@@ -39,11 +39,11 @@ import gov.cdc.prime.router.fhirengine.translation.hl7.utils.FhirPathUtils
import gov.cdc.prime.router.fhirengine.utils.FhirTranscoder
import gov.cdc.prime.router.fhirengine.utils.HL7Reader
import gov.cdc.prime.router.fhirengine.utils.getObservations
+import org.hl7.fhir.r4.fhirpath.FHIRLexer.FHIRLexerException
import org.hl7.fhir.r4.model.Base
import org.hl7.fhir.r4.model.Bundle
import org.hl7.fhir.r4.model.Extension
import org.hl7.fhir.r4.model.Reference
-import org.hl7.fhir.r4.utils.FHIRLexer.FHIRLexerException
/**
* Process data into/from FHIR.
diff --git a/prime-router/src/main/kotlin/fhirengine/engine/CustomFhirPathFunctions.kt b/prime-router/src/main/kotlin/fhirengine/engine/CustomFhirPathFunctions.kt
index 5fcfcaeb1f1..0083feea221 100644
--- a/prime-router/src/main/kotlin/fhirengine/engine/CustomFhirPathFunctions.kt
+++ b/prime-router/src/main/kotlin/fhirengine/engine/CustomFhirPathFunctions.kt
@@ -10,11 +10,11 @@ import gov.cdc.prime.router.common.NPIUtilities
import gov.cdc.prime.router.fhirengine.translation.hl7.SchemaException
import gov.cdc.prime.router.metadata.GeoData
import gov.cdc.prime.router.metadata.LivdLookup
+import org.hl7.fhir.r4.fhirpath.FHIRPathUtilityClasses.FunctionDetails
import org.hl7.fhir.r4.model.Base
import org.hl7.fhir.r4.model.Device
import org.hl7.fhir.r4.model.Observation
import org.hl7.fhir.r4.model.StringType
-import org.hl7.fhir.r4.utils.FHIRPathUtilityClasses.FunctionDetails
import java.time.LocalDate
import java.util.Date
import java.util.UUID
diff --git a/prime-router/src/main/kotlin/fhirengine/translation/hl7/utils/ConstantResolver.kt b/prime-router/src/main/kotlin/fhirengine/translation/hl7/utils/ConstantResolver.kt
index 5263b8c0ad4..d15800abd95 100644
--- a/prime-router/src/main/kotlin/fhirengine/translation/hl7/utils/ConstantResolver.kt
+++ b/prime-router/src/main/kotlin/fhirengine/translation/hl7/utils/ConstantResolver.kt
@@ -9,14 +9,14 @@ import org.apache.commons.text.StringSubstitutor
import org.apache.commons.text.lookup.StringLookup
import org.apache.logging.log4j.kotlin.Logging
import org.hl7.fhir.exceptions.PathEngineException
+import org.hl7.fhir.r4.fhirpath.FHIRPathEngine
+import org.hl7.fhir.r4.fhirpath.FHIRPathUtilityClasses
+import org.hl7.fhir.r4.fhirpath.TypeDetails
import org.hl7.fhir.r4.model.Base
import org.hl7.fhir.r4.model.Bundle
import org.hl7.fhir.r4.model.IntegerType
import org.hl7.fhir.r4.model.StringType
-import org.hl7.fhir.r4.model.TypeDetails
import org.hl7.fhir.r4.model.ValueSet
-import org.hl7.fhir.r4.utils.FHIRPathEngine
-import org.hl7.fhir.r4.utils.FHIRPathUtilityClasses.FunctionDetails
import java.lang.IllegalArgumentException
import java.lang.NumberFormatException
@@ -145,7 +145,13 @@ class ConstantSubstitutor {
*/
class FhirPathCustomResolver(private val customFhirFunctions: FhirPathFunctions? = null) :
FHIRPathEngine.IEvaluationContext, Logging {
- override fun resolveConstant(appContext: Any?, name: String?, beforeContext: Boolean): List {
+ override fun resolveConstant(
+ engine: FHIRPathEngine?,
+ appContext: Any?,
+ name: String?,
+ beforeContext: Boolean,
+ explicitConstant: Boolean,
+ ): List {
// Name is always passed in from the FHIR path engine
require(!name.isNullOrBlank())
@@ -210,7 +216,12 @@ class FhirPathCustomResolver(private val customFhirFunctions: FhirPathFunctions?
}
}
- override fun resolveConstantType(appContext: Any?, name: String?): TypeDetails {
+ override fun resolveConstantType(
+ engine: FHIRPathEngine?,
+ appContext: Any?,
+ name: String?,
+ explicitConstant: Boolean,
+ ): TypeDetails {
throw NotImplementedError("Not implemented")
}
@@ -218,19 +229,25 @@ class FhirPathCustomResolver(private val customFhirFunctions: FhirPathFunctions?
throw NotImplementedError("Not implemented")
}
- override fun resolveFunction(functionName: String?): FunctionDetails? {
+ override fun resolveFunction(
+ engine: FHIRPathEngine?,
+ functionName: String?,
+ ): FHIRPathUtilityClasses.FunctionDetails? {
return CustomFHIRFunctions.resolveFunction(functionName, customFhirFunctions)
}
override fun checkFunction(
+ engine: FHIRPathEngine?,
appContext: Any?,
functionName: String?,
+ focus: TypeDetails?,
parameters: MutableList?,
): TypeDetails {
throw NotImplementedError("Not implemented")
}
override fun executeFunction(
+ engine: FHIRPathEngine?,
appContext: Any?,
focus: MutableList?,
functionName: String?,
@@ -246,7 +263,7 @@ class FhirPathCustomResolver(private val customFhirFunctions: FhirPathFunctions?
}
}
- override fun resolveReference(appContext: Any?, url: String?, refContext: Base?): Base? {
+ override fun resolveReference(engine: FHIRPathEngine?, appContext: Any?, url: String?, refContext: Base?): Base? {
// Name is always passed in from the FHIR path engine
require(!url.isNullOrBlank())
@@ -256,11 +273,11 @@ class FhirPathCustomResolver(private val customFhirFunctions: FhirPathFunctions?
}
}
- override fun conformsToProfile(appContext: Any?, item: Base?, url: String?): Boolean {
+ override fun conformsToProfile(engine: FHIRPathEngine?, appContext: Any?, item: Base?, url: String?): Boolean {
throw NotImplementedError("Not implemented")
}
- override fun resolveValueSet(appContext: Any?, url: String?): ValueSet {
+ override fun resolveValueSet(engine: FHIRPathEngine?, appContext: Any?, url: String?): ValueSet {
throw NotImplementedError("Not implemented")
}
}
\ No newline at end of file
diff --git a/prime-router/src/main/kotlin/fhirengine/translation/hl7/utils/CustomFHIRFunctions.kt b/prime-router/src/main/kotlin/fhirengine/translation/hl7/utils/CustomFHIRFunctions.kt
index 8b6fb6f0734..e6986f75388 100644
--- a/prime-router/src/main/kotlin/fhirengine/translation/hl7/utils/CustomFHIRFunctions.kt
+++ b/prime-router/src/main/kotlin/fhirengine/translation/hl7/utils/CustomFHIRFunctions.kt
@@ -4,13 +4,13 @@ import ca.uhn.fhir.model.api.TemporalPrecisionEnum
import fhirengine.translation.hl7.utils.FhirPathFunctions
import fhirengine.translation.hl7.utils.helpers.convertDateToAge
import gov.cdc.prime.router.fhirengine.translation.hl7.SchemaException
+import org.hl7.fhir.r4.fhirpath.FHIRPathUtilityClasses.FunctionDetails
import org.hl7.fhir.r4.model.Base
import org.hl7.fhir.r4.model.BaseDateTimeType
import org.hl7.fhir.r4.model.BooleanType
import org.hl7.fhir.r4.model.DateTimeType
import org.hl7.fhir.r4.model.IntegerType
import org.hl7.fhir.r4.model.StringType
-import org.hl7.fhir.r4.utils.FHIRPathUtilityClasses.FunctionDetails
import java.time.DateTimeException
import java.time.ZoneId
import java.util.TimeZone
diff --git a/prime-router/src/main/kotlin/fhirengine/translation/hl7/utils/FhirPathFunctions.kt b/prime-router/src/main/kotlin/fhirengine/translation/hl7/utils/FhirPathFunctions.kt
index 19128b571c3..6a7d0da648c 100644
--- a/prime-router/src/main/kotlin/fhirengine/translation/hl7/utils/FhirPathFunctions.kt
+++ b/prime-router/src/main/kotlin/fhirengine/translation/hl7/utils/FhirPathFunctions.kt
@@ -1,7 +1,8 @@
package fhirengine.translation.hl7.utils
+import org.hl7.fhir.r4.fhirpath.FHIRPathUtilityClasses.FunctionDetails
import org.hl7.fhir.r4.model.Base
-import org.hl7.fhir.r4.utils.FHIRPathUtilityClasses.FunctionDetails
+
/**
* This interface contains the required method signatures required to implement custom FHIR functions
*/
diff --git a/prime-router/src/main/kotlin/fhirengine/translation/hl7/utils/FhirPathUtils.kt b/prime-router/src/main/kotlin/fhirengine/translation/hl7/utils/FhirPathUtils.kt
index d658e2d73f2..e7328517f36 100644
--- a/prime-router/src/main/kotlin/fhirengine/translation/hl7/utils/FhirPathUtils.kt
+++ b/prime-router/src/main/kotlin/fhirengine/translation/hl7/utils/FhirPathUtils.kt
@@ -8,6 +8,9 @@ import gov.cdc.prime.router.fhirengine.translation.hl7.HL7ConversionException
import gov.cdc.prime.router.fhirengine.translation.hl7.SchemaException
import gov.cdc.prime.router.fhirengine.translation.hl7.schema.converter.ConverterSchemaElement
import org.apache.logging.log4j.kotlin.Logging
+import org.hl7.fhir.r4.fhirpath.ExpressionNode
+import org.hl7.fhir.r4.fhirpath.FHIRLexer
+import org.hl7.fhir.r4.fhirpath.FHIRPathEngine
import org.hl7.fhir.r4.hapi.ctx.HapiWorkerContext
import org.hl7.fhir.r4.model.Base
import org.hl7.fhir.r4.model.BaseDateTimeType
@@ -15,11 +18,8 @@ import org.hl7.fhir.r4.model.BooleanType
import org.hl7.fhir.r4.model.Bundle
import org.hl7.fhir.r4.model.DateTimeType
import org.hl7.fhir.r4.model.DateType
-import org.hl7.fhir.r4.model.ExpressionNode
import org.hl7.fhir.r4.model.InstantType
import org.hl7.fhir.r4.model.TimeType
-import org.hl7.fhir.r4.utils.FHIRLexer.FHIRLexerException
-import org.hl7.fhir.r4.utils.FHIRPathEngine
import java.time.DateTimeException
import java.time.LocalTime
import java.time.format.DateTimeFormatter
@@ -97,7 +97,7 @@ object FhirPathUtils : Logging {
} else {
pathEngine.evaluate(appContext, focusResource, bundle, bundle, expressionNode)
}
- } catch (e: FHIRLexerException) {
+ } catch (e: FHIRLexer.FHIRLexerException) {
logger.error("${e.javaClass.name}: Syntax error in FHIR Path $expression.")
emptyList()
} catch (e: IndexOutOfBoundsException) {
@@ -145,7 +145,7 @@ object FhirPathUtils : Logging {
}
} catch (e: Exception) {
val msg = when (e) {
- is FHIRLexerException -> "Syntax error in FHIR Path expression $expression"
+ is FHIRLexer.FHIRLexerException -> "Syntax error in FHIR Path expression $expression"
is SchemaException -> e.message.toString()
else ->
"Unknown error while evaluating FHIR Path expression $expression for condition. " +
diff --git a/prime-router/src/test/kotlin/fhirengine/translation/hl7/utils/ConstantResolverTests.kt b/prime-router/src/test/kotlin/fhirengine/translation/hl7/utils/ConstantResolverTests.kt
index 7920025ac12..7f55193b5b0 100644
--- a/prime-router/src/test/kotlin/fhirengine/translation/hl7/utils/ConstantResolverTests.kt
+++ b/prime-router/src/test/kotlin/fhirengine/translation/hl7/utils/ConstantResolverTests.kt
@@ -86,24 +86,24 @@ class ConstantResolverTests {
@Test
fun `test fhir path resolver`() {
mockkObject(FhirPathUtils)
- assertFailure { FhirPathCustomResolver().resolveConstant(null, null, false) }
- assertFailure { FhirPathCustomResolver().resolveConstant(null, "const1", false) }
+ assertFailure { FhirPathCustomResolver().resolveConstant(null, null, null, false, false) }
+ assertFailure { FhirPathCustomResolver().resolveConstant(null, null, "const1", false, false) }
.hasClass(PathEngineException::class.java)
val integerValue = 99
val urlPrefix = "https://reportstream.cdc.gov/fhir/StructureDefinition/"
val constants = sortedMapOf("const1" to "'value1'", "int1" to "'$integerValue'", "rsext" to "'$urlPrefix'")
val context = CustomContext.addConstants(constants, CustomContext(Bundle(), Bundle()))
- assertThat(FhirPathCustomResolver().resolveConstant(context, "const2", false)).isEmpty()
- assertThat(FhirPathCustomResolver().resolveConstant(context, "const1", false)).isNotNull()
- var result = FhirPathCustomResolver().resolveConstant(context, "int1", false)
+ assertThat(FhirPathCustomResolver().resolveConstant(null, context, "const2", false, false)).isEmpty()
+ assertThat(FhirPathCustomResolver().resolveConstant(null, context, "const1", false, false)).isNotNull()
+ var result = FhirPathCustomResolver().resolveConstant(null, context, "int1", false, false)
assertThat(result).isNotNull()
assertThat(result).isNotEmpty()
assertThat(result[0] is IntegerType).isTrue()
assertThat((result[0] as IntegerType).value).isEqualTo(integerValue)
// Now lets resolve a constant
- result = FhirPathCustomResolver().resolveConstant(context, "const1", false)
+ result = FhirPathCustomResolver().resolveConstant(null, context, "const1", false, false)
assertThat(result).isNotNull()
assertThat(result.isNotEmpty())
assertThat(result[0].isPrimitive).isTrue()
@@ -114,21 +114,21 @@ class ConstantResolverTests {
// Test the ability to resolve constants with suffix
val urlSuffix = "SomeSuffix"
- result = FhirPathCustomResolver().resolveConstant(context, "`rsext-$urlSuffix`", false)
+ result = FhirPathCustomResolver().resolveConstant(null, context, "`rsext-$urlSuffix`", false, false)
assertThat(result).isNotNull()
assertThat(result.isNotEmpty())
assertThat(result[0].isPrimitive).isTrue()
assertThat(result[0]).isInstanceOf(StringType::class.java)
assertThat((result[0] as StringType).value).isEqualTo("$urlPrefix$urlSuffix")
- result = FhirPathCustomResolver().resolveConstant(context, "`rsext`", false)
+ result = FhirPathCustomResolver().resolveConstant(null, context, "`rsext`", false, false)
assertThat(result).isNotNull()
assertThat(result.isNotEmpty())
assertThat(result[0].isPrimitive).isTrue()
assertThat(result[0]).isInstanceOf(StringType::class.java)
assertThat((result[0] as StringType).value).isEqualTo(urlPrefix)
- result = FhirPathCustomResolver().resolveConstant(context, "unknownconst", false)
+ result = FhirPathCustomResolver().resolveConstant(null, context, "unknownconst", false, false)
assertThat(result).isEmpty()
}
@@ -144,7 +144,7 @@ class ConstantResolverTests {
val constants = sortedMapOf("const1" to "'value1'") // this does not matter but context wants something
val context = CustomContext.addConstants(constants, CustomContext(Bundle(), Bundle()))
- val result = FhirPathCustomResolver().resolveConstant(context, "const1", false)
+ val result = FhirPathCustomResolver().resolveConstant(null, context, "const1", false, false)
assertThat(result).isNotNull()
assertThat(result.isNotEmpty())
assertThat(result.size == 3)
@@ -167,6 +167,7 @@ class ConstantResolverTests {
val context = CustomContext(Bundle(), Bundle())
assertThat(
FhirPathCustomResolver(CustomFhirPathFunctions()).executeFunction(
+ null,
context,
mutableListOf(Observation()),
"livdTableLookup",
@@ -180,6 +181,7 @@ class ConstantResolverTests {
val context = CustomContext(Bundle(), Bundle())
assertFailure {
FhirPathCustomResolver(CustomFhirPathFunctions()).executeFunction(
+ null,
context,
mutableListOf(Observation()),
"unknown",
@@ -198,15 +200,15 @@ class ConstantResolverTests {
val bundle = Bundle()
val customContext = CustomContext(bundle, bundle)
- assertThat(FhirPathCustomResolver().resolveReference(customContext, org2Url, null)).isNull()
+ assertThat(FhirPathCustomResolver().resolveReference(null, customContext, org2Url, null)).isNull()
bundle.addEntry().resource = org1
bundle.entry[0].fullUrl = "Organization/${org1.id}"
- assertThat(FhirPathCustomResolver().resolveReference(customContext, org2Url, null)).isNull()
+ assertThat(FhirPathCustomResolver().resolveReference(null, customContext, org2Url, null)).isNull()
bundle.addEntry().resource = org2
bundle.entry[1].fullUrl = org2Url
- val reference = FhirPathCustomResolver().resolveReference(customContext, org2Url, null)
+ val reference = FhirPathCustomResolver().resolveReference(null, customContext, org2Url, null)
assertThat(reference).isNotNull()
assertThat(reference).isEqualTo(org2)
}
diff --git a/prime-router/src/test/kotlin/fhirengine/translation/hl7/utils/FhirPathUtilsTests.kt b/prime-router/src/test/kotlin/fhirengine/translation/hl7/utils/FhirPathUtilsTests.kt
index e228719e1ca..173f4a61642 100644
--- a/prime-router/src/test/kotlin/fhirengine/translation/hl7/utils/FhirPathUtilsTests.kt
+++ b/prime-router/src/test/kotlin/fhirengine/translation/hl7/utils/FhirPathUtilsTests.kt
@@ -28,6 +28,7 @@ import io.mockk.spyk
import io.mockk.verify
import org.apache.logging.log4j.kotlin.KotlinLogger
import org.hl7.fhir.exceptions.PathEngineException
+import org.hl7.fhir.r4.fhirpath.FHIRLexer
import org.hl7.fhir.r4.model.Bundle
import org.hl7.fhir.r4.model.DateTimeType
import org.hl7.fhir.r4.model.DateType
@@ -37,7 +38,6 @@ import org.hl7.fhir.r4.model.InstantType
import org.hl7.fhir.r4.model.Observation
import org.hl7.fhir.r4.model.ServiceRequest
import org.hl7.fhir.r4.model.TimeType
-import org.hl7.fhir.r4.utils.FHIRLexer.FHIRLexerException
import org.junit.jupiter.api.BeforeEach
import java.util.Date
import kotlin.test.Test
@@ -69,7 +69,7 @@ class FhirPathUtilsTests {
assertThat(FhirPathUtils.parsePath("")).isNull()
// Invalid fhir path syntax
- assertFailsWith { FhirPathUtils.parsePath("Bundle.#*($&id.exists()") }
+ assertFailsWith { FhirPathUtils.parsePath("Bundle.#*($&id.exists()") }
}
@Test
@@ -101,7 +101,7 @@ class FhirPathUtilsTests {
FhirPathUtils.evaluateCondition(null, bundle, bundle, bundle, path)
} catch (e: Exception) {
assertThat(e).isInstanceOf()
- assertThat(e.cause).isNotNull().isInstanceOf()
+ assertThat(e.cause).isNotNull().isInstanceOf()
}
}
@@ -193,7 +193,7 @@ class FhirPathUtilsTests {
verify {
mockedLogger.error(
- "org.hl7.fhir.r4.utils.FHIRLexer\$FHIRLexerException: " +
+ "org.hl7.fhir.r4.fhirpath.FHIRLexer\$FHIRLexerException: " +
"Syntax error in FHIR Path Bundle.#*(\$&id.exists()."
)
}