Skip to content

Commit 9bd76c8

Browse files
authored
Update clinical reasoning dependencies (#2637)
* Update clinical reasoning dependencies * Fix smart immunizations tests * Fix build for PlanDefinition.kt * Add licencee exceptions * Update tests * Fix cql builder and add package exclusion * Fix build for workflow benchmark * Update tests and build * Run spotless * Fix logback dependency in workflow:benchmark * Add exclusion of logback-classic for the whole project
1 parent 2ee4c58 commit 9bd76c8

File tree

25 files changed

+147
-137
lines changed

25 files changed

+147
-137
lines changed

buildSrc/src/main/kotlin/Dependencies.kt

+8-20
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,6 @@ import org.gradle.api.artifacts.DependencyConstraint
1919
import org.gradle.kotlin.dsl.exclude
2020

2121
object Dependencies {
22-
object Cql {
23-
const val evaluator = "org.opencds.cqf.fhir:cqf-fhir-cr:${Versions.Cql.clinicalReasoning}"
24-
const val evaluatorFhirJackson =
25-
"org.opencds.cqf.fhir:cqf-fhir-jackson:${Versions.Cql.clinicalReasoning}"
26-
const val evaluatorFhirUtilities =
27-
"org.opencds.cqf.fhir:cqf-fhir-utility:${Versions.Cql.clinicalReasoning}"
28-
}
29-
3022
object HapiFhir {
3123
const val fhirBaseModule = "ca.uhn.hapi.fhir:hapi-fhir-base"
3224
const val fhirClientModule = "ca.uhn.hapi.fhir:hapi-fhir-client"
@@ -139,11 +131,6 @@ object Dependencies {
139131
const val xmlUnit = "org.xmlunit:xmlunit-core:${Versions.xmlUnit}"
140132

141133
object Versions {
142-
143-
object Cql {
144-
const val clinicalReasoning = "3.0.0-PRE9-SNAPSHOT"
145-
}
146-
147134
const val androidFhirCommon = "0.1.0-alpha05"
148135
const val androidFhirEngine = "0.1.0-beta05"
149136
const val androidFhirKnowledge = "0.1.0-alpha03"
@@ -195,16 +182,17 @@ object Dependencies {
195182
}
196183

197184
fun Configuration.removeIncompatibleDependencies() {
198-
exclude(module = "xpp3")
199-
exclude(module = "xpp3_min")
200-
exclude(module = "xmlpull")
185+
exclude(module = "hapi-fhir-caching-caffeine")
201186
exclude(module = "javax.json")
202187
exclude(module = "jcl-over-slf4j")
203-
exclude(group = "org.apache.httpcomponents")
204-
exclude(group = "org.antlr", module = "antlr4")
205-
exclude(group = "org.eclipse.persistence", module = "org.eclipse.persistence.moxy")
206-
exclude(module = "hapi-fhir-caching-caffeine")
188+
exclude(module = "xmlpull")
189+
exclude(module = "xpp3")
190+
exclude(module = "xpp3_min")
191+
exclude(group = "ch.qos.logback", module = "logback-classic")
207192
exclude(group = "com.github.ben-manes.caffeine", module = "caffeine")
193+
exclude(group = "org.eclipse.persistence", module = "org.eclipse.persistence.moxy")
194+
exclude(group = "org.antlr", module = "antlr4")
195+
exclude(group = "org.apache.httpcomponents")
208196
}
209197

210198
fun hapiFhirConstraints(): Map<String, DependencyConstraint.() -> Unit> {

buildSrc/src/main/kotlin/LicenseeConfig.kt

+16-3
Original file line numberDiff line numberDiff line change
@@ -72,17 +72,24 @@ fun Project.configureLicensee() {
7272
}
7373

7474
// Jakarta XML Binding API
75-
allowDependency("jakarta.xml.bind", "jakarta.xml.bind-api", "2.3.3") {
75+
allowDependency("jakarta.xml.bind", "jakarta.xml.bind-api", "4.0.1") {
7676
because("BSD 3-clause.")
7777
}
7878

7979
// Jakarta Activation API 2.1 Specification
80-
allowDependency("jakarta.activation", "jakarta.activation-api", "1.2.2") {
80+
allowDependency("jakarta.activation", "jakarta.activation-api", "2.1.2") {
8181
because(
8282
"Licensed under Eclipse Distribution License 1.0. http://www.eclipse.org/org/documents/edl-v10.php",
8383
)
8484
}
8585

86+
// Jakarta Annotation API 2.1 Specification
87+
allowDependency("jakarta.annotation", "jakarta.annotation-api", "2.1.1") {
88+
because(
89+
"Licensed under EPL 2.0",
90+
)
91+
}
92+
8693
// Javax Annotation API
8794
allowDependency("javax.annotation", "javax.annotation-api", "1.3.2") {
8895
because("Dual-licensed under CDDL 1.1 and GPL v2 with classpath exception.")
@@ -108,7 +115,7 @@ fun Project.configureLicensee() {
108115
because("BSD 3-clause. http://www.antlr.org/license.html")
109116
}
110117
// ANTLR 4
111-
allowDependency("org.antlr", "antlr4-runtime", "4.10.1") {
118+
allowDependency("org.antlr", "antlr4-runtime", "4.13.1") {
112119
because("BSD 3-clause. http://www.antlr.org/license.html")
113120
}
114121

@@ -195,6 +202,12 @@ fun Project.configureLicensee() {
195202
allowDependency("com.ibm.icu", "icu4j", "72.1") {
196203
because("BSD, part MIT and Apache 2.0. https://github.com/unicode-org/icu/blob/main/LICENSE")
197204
}
205+
206+
// Logback
207+
allowDependency("ch.qos.logback", "logback-classic", "1.4.14") { because("LGPL") }
208+
209+
// Logback
210+
allowDependency("ch.qos.logback", "logback-core", "1.4.14") { because("LGPL") }
198211
}
199212
}
200213

gradle/libs.versions.toml

+7-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ junit = "4.13.2"
2525
kotlin-stdlib = "1.9.22"
2626
kotlin-test = "1.9.22"
2727
kotlinx-coroutines = "1.8.1"
28+
logback-android = "3.0.0"
29+
opencds-cqf-fhir = "3.8.0"
2830
truth = "1.1.5"
2931

3032
[libraries]
@@ -58,13 +60,17 @@ androidx-test-runner = { module = "androidx.test:runner", version.ref = "android
5860
androidx-work-runtime = { module = "androidx.work:work-runtime-ktx", version.ref = "androidx-work" }
5961
androidx-work-testing = { module = "androidx.work:work-testing", version.ref = "androidx-work" }
6062
glide = { module = "com.github.bumptech.glide:glide", version.ref = "glide" }
63+
junit = { module = "junit:junit", version.ref = "junit" }
6164
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin-stdlib" }
6265
kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin-test" }
6366
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
6467
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
6568
kotlinx-coroutines-playservices = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-play-services", version.ref = "kotlinx-coroutines" }
6669
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
67-
junit = { module = "junit:junit", version.ref = "junit" }
70+
logback-android = { module = "com.github.tony19:logback-android", version.ref = "logback-android" }
71+
opencds-cqf-fhir-cr = { module = "org.opencds.cqf.fhir:cqf-fhir-cr", version.ref = "opencds-cqf-fhir" }
72+
opencds-cqf-fhir-jackson = { module = "org.opencds.cqf.fhir:cqf-fhir-jackson", version.ref = "opencds-cqf-fhir" }
73+
opencds-cqf-fhir-utility = { module = "org.opencds.cqf.fhir:cqf-fhir-utility", version.ref = "opencds-cqf-fhir" }
6874
truth = { module = "com.google.truth:truth", version.ref = "truth" }
6975

7076
[bundles]

workflow-testing/build.gradle.kts

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ android {
1515
configurations { all { removeIncompatibleDependencies() } }
1616

1717
dependencies {
18-
compileOnly(Dependencies.Cql.evaluator)
19-
compileOnly(Dependencies.Cql.evaluatorFhirJackson)
20-
compileOnly(Dependencies.Cql.evaluatorFhirUtilities)
18+
compileOnly(libs.opencds.cqf.fhir.cr)
19+
compileOnly(libs.opencds.cqf.fhir.jackson)
20+
compileOnly(libs.opencds.cqf.fhir.utility)
2121
compileOnly(project(":engine")) { exclude(module = "truth") }
2222

2323
compileOnly(Dependencies.jsonAssert)

workflow-testing/src/main/java/com/google/android/fhir/workflow/testing/CqlBuilder.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ object CqlBuilder : Loadable() {
120120
version = libVersion
121121
status = Enumerations.PublicationStatus.ACTIVE
122122
experimental = true
123-
url = "http://localhost/Library/$libName|$libVersion"
123+
url = "http://localhost/Library/$libName"
124124
attachmentCql?.let { addContent(it) }
125125
attachmentJson?.let { addContent(it) }
126126
attachmentXml?.let { addContent(it) }

workflow-testing/src/main/java/com/google/android/fhir/workflow/testing/IGInputStreamStructureRepository.kt

+41-31
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023 Google LLC
2+
* Copyright 2023-2024 Google LLC
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@ import ca.uhn.fhir.util.BundleBuilder
2828
import com.google.common.collect.ImmutableMap
2929
import java.io.File
3030
import java.io.FileNotFoundException
31-
import java.util.Locale
3231
import java.util.Objects
3332
import java.util.function.Consumer
3433
import org.hl7.fhir.instance.model.api.IBaseBundle
@@ -40,9 +39,7 @@ import org.opencds.cqf.fhir.api.Repository
4039
import org.opencds.cqf.fhir.utility.Ids
4140
import org.opencds.cqf.fhir.utility.dstu3.AttachmentUtil
4241
import org.opencds.cqf.fhir.utility.matcher.ResourceMatcher
43-
import org.opencds.cqf.fhir.utility.repository.IGLayoutMode
4442
import org.opencds.cqf.fhir.utility.repository.Repositories
45-
import org.opencds.cqf.fhir.utility.repository.ResourceCategory
4643

4744
/**
4845
* This class implements the Repository interface on onto a directory structure that matches the
@@ -51,7 +48,6 @@ import org.opencds.cqf.fhir.utility.repository.ResourceCategory
5148
class IGInputStreamStructureRepository(
5249
private val fhirContext: FhirContext,
5350
private val root: String? = null,
54-
private val layoutMode: IGLayoutMode = IGLayoutMode.DIRECTORY,
5551
private val encodingEnum: EncodingEnum = EncodingEnum.JSON,
5652
) : Loadable(), Repository {
5753
private val resourceCache: MutableMap<String, IBaseResource> = HashMap()
@@ -62,42 +58,32 @@ class IGInputStreamStructureRepository(
6258
resourceCache.clear()
6359
}
6460

65-
protected fun <T : IBaseResource?, I : IIdType?> locationForResource(
61+
private fun <T : IBaseResource?, I : IIdType?> locationForResource(
6662
resourceType: Class<T>,
6763
id: I,
6864
): String {
6965
val directory = directoryForType(resourceType)
7066
return directory + "/" + fileNameForLayoutAndEncoding(resourceType.simpleName, id!!.idPart)
7167
}
7268

73-
protected fun fileNameForLayoutAndEncoding(resourceType: String, resourceId: String): String {
69+
private fun fileNameForLayoutAndEncoding(resourceType: String, resourceId: String): String {
7470
val name = resourceId + fileExtensions[encodingEnum]
75-
return if (layoutMode === IGLayoutMode.DIRECTORY) {
76-
// TODO: case sensitivity!!
77-
resourceType.lowercase(Locale.getDefault()) + "/" + name
78-
} else {
79-
"$resourceType-$name"
80-
}
71+
return "$resourceType-$name"
8172
}
8273

83-
protected fun <T : IBaseResource?> directoryForType(resourceType: Class<T>): String {
74+
private fun <T : IBaseResource?> directoryForType(resourceType: Class<T>): String {
8475
val category = ResourceCategory.forType(resourceType.simpleName)
8576
val directory = categoryDirectories[category]
8677

8778
// TODO: what the heck is the path separator?
8879
return (if (root!!.endsWith("/")) root else "$root/") + directory
8980
}
9081

91-
protected fun <T : IBaseResource?> directoryForResource(resourceType: Class<T>): String {
92-
val directory = directoryForType(resourceType)
93-
return if (layoutMode === IGLayoutMode.DIRECTORY) {
94-
directory + "/" + resourceType.simpleName.lowercase(Locale.getDefault())
95-
} else {
96-
directory
97-
}
82+
private fun <T : IBaseResource?> directoryForResource(resourceType: Class<T>): String {
83+
return directoryForType(resourceType)
9884
}
9985

100-
protected fun <T : IBaseResource, I : IIdType> readLocation(
86+
private fun <T : IBaseResource, I : IIdType> readLocation(
10187
resourceClass: Class<T>?,
10288
location: String,
10389
): T {
@@ -112,7 +98,7 @@ class IGInputStreamStructureRepository(
11298
} as T
11399
}
114100

115-
protected fun <T : IBaseResource> handleLibrary(resource: T, location: String?): T {
101+
private fun <T : IBaseResource> handleLibrary(resource: T, location: String?): T {
116102
var resourceOutput = resource
117103
if (resourceOutput.fhirType() == "Library") {
118104
val cqlLocation: String?
@@ -161,7 +147,7 @@ class IGInputStreamStructureRepository(
161147
return resourceOutput
162148
}
163149

164-
protected fun getCqlContent(rootPath: String?, relativePath: String?): String {
150+
private fun getCqlContent(rootPath: String?, relativePath: String?): String {
165151
val p = File(File(rootPath).parent, relativePath).normalize().toString()
166152
return try {
167153
load(p)
@@ -171,18 +157,14 @@ class IGInputStreamStructureRepository(
171157
}
172158
}
173159

174-
protected fun <T : IBaseResource> readLocation(resourceClass: Class<T>): Map<IIdType, T> {
160+
private fun <T : IBaseResource> readLocation(resourceClass: Class<T>): Map<IIdType, T> {
175161
val location = directoryForResource(resourceClass)
176162
val resources = HashMap<IIdType, T>()
177163

178164
val inputFiles = listFiles(location)
179165

180166
for (file in inputFiles) {
181-
if (
182-
layoutMode.equals(IGLayoutMode.DIRECTORY) ||
183-
(layoutMode.equals(IGLayoutMode.TYPE_PREFIX) &&
184-
file.startsWith(resourceClass.simpleName + "-"))
185-
) {
167+
if (file.startsWith(resourceClass.simpleName + "-")) {
186168
try {
187169
val r = this.readLocation<T, IIdType>(resourceClass, "$location/$file")
188170
if (r.fhirType() == resourceClass.simpleName) {
@@ -282,7 +264,7 @@ class IGInputStreamStructureRepository(
282264
): B {
283265
val builder = BundleBuilder(fhirContext)
284266
val resourceIdMap = readLocation(resourceType)
285-
if (searchParameters == null || searchParameters.isEmpty()) {
267+
if (searchParameters.isEmpty()) {
286268
resourceIdMap.values.forEach(
287269
Consumer { theResource: T ->
288270
builder.addCollectionEntry(
@@ -442,6 +424,34 @@ class IGInputStreamStructureRepository(
442424
}
443425

444426
companion object {
427+
enum class ResourceCategory {
428+
DATA,
429+
TERMINOLOGY,
430+
CONTENT,
431+
;
432+
433+
companion object {
434+
private val TERMINOLOGY_RESOURCES: Set<String> = hashSetOf("ValueSet", "CodeSystem")
435+
private val CONTENT_RESOURCES: Set<String> =
436+
hashSetOf(
437+
"Library",
438+
"Questionnaire",
439+
"Measure",
440+
"PlanDefinition",
441+
"StructureDefinition",
442+
"ActivityDefinition",
443+
)
444+
445+
fun forType(resourceType: String): ResourceCategory {
446+
return if (TERMINOLOGY_RESOURCES.contains(resourceType)) {
447+
TERMINOLOGY
448+
} else {
449+
if (CONTENT_RESOURCES.contains(resourceType)) CONTENT else DATA
450+
}
451+
}
452+
}
453+
}
454+
445455
private val categoryDirectories: Map<ResourceCategory, String> =
446456
ImmutableMap.Builder<ResourceCategory, String>()
447457
.put(ResourceCategory.CONTENT, "resources")

workflow-testing/src/main/java/com/google/android/fhir/workflow/testing/PlanDefinition.kt

+13-21
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2022-2023 Google LLC
2+
* Copyright 2022-2024 Google LLC
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,7 +21,6 @@ import ca.uhn.fhir.context.FhirVersionEnum
2121
import ca.uhn.fhir.rest.api.EncodingEnum
2222
import java.io.IOException
2323
import org.hl7.fhir.instance.model.api.IBaseResource
24-
import org.hl7.fhir.instance.model.api.IPrimitiveType
2524
import org.hl7.fhir.r4.model.Bundle
2625
import org.hl7.fhir.r4.model.CarePlan
2726
import org.hl7.fhir.r4.model.CommunicationRequest
@@ -38,8 +37,8 @@ import org.junit.Assert.fail
3837
import org.opencds.cqf.fhir.api.Repository
3938
import org.opencds.cqf.fhir.cql.EvaluationSettings
4039
import org.opencds.cqf.fhir.cql.LibraryEngine
41-
import org.opencds.cqf.fhir.cr.plandefinition.r4.PlanDefinitionProcessor
42-
import org.opencds.cqf.fhir.utility.repository.IGLayoutMode
40+
import org.opencds.cqf.fhir.cr.plandefinition.PlanDefinitionProcessor
41+
import org.opencds.cqf.fhir.utility.monad.Eithers
4342
import org.opencds.cqf.fhir.utility.repository.InMemoryFhirRepository
4443
import org.opencds.cqf.fhir.utility.repository.Repositories
4544
import org.skyscreamer.jsonassert.JSONAssert
@@ -152,7 +151,6 @@ object PlanDefinition : Loadable() {
152151
IGInputStreamStructureRepository(
153152
fhirContext,
154153
repositoryPath ?: ".",
155-
IGLayoutMode.TYPE_PREFIX,
156154
EncodingEnum.JSON,
157155
)
158156
if (dataRepository == null && contentRepository == null && terminologyRepository == null) {
@@ -200,14 +198,12 @@ object PlanDefinition : Loadable() {
200198

201199
return GeneratedBundle(
202200
buildProcessor(repository)
203-
.applyR5<IPrimitiveType<String>>(
204-
/* id = */ IdType("PlanDefinition", planDefinitionID),
205-
/* canonical = */ null,
206-
/* planDefinition = */ null,
207-
/* patientId = */ patientID,
208-
/* encounterId = */ encounterID,
209-
/* practitionerId = */ practitionerID,
210-
/* organizationId = */ null,
201+
.applyR5(
202+
/* planDefinition = */ Eithers.forMiddle3(IdType("PlanDefinition", planDefinitionID)),
203+
/* subject = */ patientID,
204+
/* encounter = */ encounterID,
205+
/* practitioner = */ practitionerID,
206+
/* organization = */ null,
211207
/* userType = */ null,
212208
/* userLanguage = */ null,
213209
/* userTaskContext = */ null,
@@ -253,10 +249,8 @@ object PlanDefinition : Loadable() {
253249

254250
return GeneratedCarePlan(
255251
(buildProcessor(repository)
256-
.apply<IPrimitiveType<String>>(
257-
IdType("PlanDefinition", planDefinitionID),
258-
null,
259-
null,
252+
.apply(
253+
/* planDefinition = */ Eithers.forMiddle3(IdType("PlanDefinition", planDefinitionID)),
260254
patientID,
261255
encounterID,
262256
practitionerID,
@@ -280,10 +274,8 @@ object PlanDefinition : Loadable() {
280274
val repository = overrideRepository ?: buildRepository()
281275
return GeneratedPackage(
282276
(buildProcessor(repository)
283-
.packagePlanDefinition<IPrimitiveType<String>>(
284-
IdType("PlanDefinition", planDefinitionID),
285-
null,
286-
null,
277+
.packagePlanDefinition(
278+
Eithers.forMiddle3(IdType("PlanDefinition", planDefinitionID)),
287279
true,
288280
) as Bundle),
289281
null,

0 commit comments

Comments
 (0)