Skip to content

Commit

Permalink
Implement the evaluateMeasure API in the FhirOperator.kt class (#810
Browse files Browse the repository at this point in the history
)

* Implement evaluateMeasure in FhirOperator that carries out the evaluate-measure operation using CQL evaluator

* Fix licensee exceptions.

* Run spotless apply
  • Loading branch information
jingtang10 authored Jan 4, 2022
1 parent e103107 commit 61f774d
Show file tree
Hide file tree
Showing 16 changed files with 33,005 additions and 18 deletions.
35 changes: 31 additions & 4 deletions buildSrc/src/main/kotlin/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ object Dependencies {
const val appCompat = "androidx.appcompat:appcompat:${Versions.Androidx.appCompat}"
const val constraintLayout =
"androidx.constraintlayout:constraintlayout:${Versions.Androidx.constraintLayout}"
const val coreKtx = "androidx.core:core-ktx:${Versions.Androidx.coreKtx}"
const val datastorePref =
"androidx.datastore:datastore-preferences:${Versions.Androidx.datastorePref}"
const val fragmentKtx = "androidx.fragment:fragment-ktx:${Versions.Androidx.fragmentKtx}"
Expand All @@ -30,17 +31,30 @@ object Dependencies {
}

object Cql {
const val cqlEngine = "org.opencds.cqf:cql-engine:${Versions.Cql.cqlEngine}"
const val cqlEngineFhir = "org.opencds.cqf:cql-engine-fhir:${Versions.Cql.cqlEngine}"
const val evaluator = "org.opencds.cqf.cql:evaluator:${Versions.Cql.evaluator}"
const val evaluatorBuilder = "org.opencds.cqf.cql:evaluator.builder:${Versions.Cql.evaluator}"
const val evaluatorDagger = "org.opencds.cqf.cql:evaluator.dagger:${Versions.Cql.evaluator}"
}

object HapiFhir {
const val structuresR4 = "ca.uhn.hapi.fhir:hapi-fhir-structures-r4:${Versions.hapiFhir}"
const val validation = "ca.uhn.hapi.fhir:hapi-fhir-validation:${Versions.hapiFhir}"
}

object Jackson {
const val annotations = "com.fasterxml.jackson.core:jackson-annotations:${Versions.jackson}"
const val core = "com.fasterxml.jackson.core:jackson-core:${Versions.jackson}"
const val databind = "com.fasterxml.jackson.core:jackson-databind:${Versions.jackson}"
}

object JavaJsonTools {
const val jacksonCoreUtils =
"com.github.java-json-tools:jackson-coreutils:${Versions.JavaJsonTools.jacksonCoreUtils}"
const val msgSimple =
"com.github.java-json-tools:msg-simple:${Versions.JavaJsonTools.msgSimple}"
}

object Kotlin {
const val androidxCoreKtx = "androidx.core:core-ktx:${Versions.Kotlin.androidxCoreKtx}"
const val kotlinCoroutinesAndroid =
"org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.Kotlin.kotlinCoroutinesCore}"
const val kotlinCoroutinesCore =
Expand Down Expand Up @@ -82,10 +96,13 @@ object Dependencies {
const val guava = "com.google.guava:guava:${Versions.guava}"
const val httpInterceptor = "com.squareup.okhttp3:logging-interceptor:${Versions.http}"
const val http = "com.squareup.okhttp3:okhttp:${Versions.http}"
const val stax = "javax.xml.stream:stax-api:${Versions.stax}"
const val jsonToolsPatch = "com.github.java-json-tools:json-patch:${Versions.jsonToolsPatch}"
const val kotlinPoet = "com.squareup:kotlinpoet:${Versions.kotlinPoet}"
const val material = "com.google.android.material:material:${Versions.material}"
const val sqlcipher = "net.zetetic:android-database-sqlcipher:${Versions.sqlcipher}"
const val woodstox = "org.codehaus.woodstox:woodstox-core-asl:${Versions.woodstox}"
const val xerces = "xerces:xercesImpl:${Versions.xerces}"

// Dependencies for testing go here
object AndroidxTest {
Expand Down Expand Up @@ -115,6 +132,7 @@ object Dependencies {
const val activity = "1.2.1"
const val appCompat = "1.1.0"
const val constraintLayout = "1.1.3"
const val coreKtx = "1.2.0"
const val datastorePref = "1.0.0"
const val fragmentKtx = "1.3.1"
const val lifecycle = "2.2.0"
Expand All @@ -127,10 +145,15 @@ object Dependencies {

object Cql {
const val cqlEngine = "1.3.14-SNAPSHOT"
const val evaluator = "1.3.1-SNAPSHOT"
}

object JavaJsonTools {
const val jacksonCoreUtils = "2.0"
const val msgSimple = "1.2"
}

object Kotlin {
const val androidxCoreKtx = "1.2.0"
const val kotlinCoroutinesCore = "1.4.2"
const val stdlib = "1.5.31"
}
Expand All @@ -144,12 +167,16 @@ object Dependencies {
// TODO: The next release of HAPI FHIR will hopefully have
// https://github.com/hapifhir/hapi-fhir/pull/3043 merged in. If it does, when we update, we
// should remove any excludes directives for "net.sf.saxon" across our build.gradle files.
const val jackson = "2.12.2"
const val jsonToolsPatch = "1.13"
const val kotlinPoet = "1.9.0"
const val material = "1.4.0"
const val retrofit = "2.7.2"
const val stax = "1.0-2"
const val sqlcipher = "4.5.0"
const val truth = "1.0.1"
const val woodstox = "4.4.1"
const val xerces = "2.11.0"

// Test dependencies

Expand Down
27 changes: 27 additions & 0 deletions buildSrc/src/main/kotlin/LicenseeConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,33 @@ fun Project.configureLicensee() {
allowDependency("net.zetetic", "android-database-sqlcipher", "4.5.0") {
because("Custom license, essentially BSD-3. https://www.zetetic.net/sqlcipher/license/")
}

// JAXB https://github.com/eclipse-ee4j/jaxb-ri
allowDependency("jakarta.xml.bind", "jakarta.xml.bind-api", "2.3.3") {
because("BSD 3-clause.")
}

// Javax Annotation API
allowDependency("javax.annotation", "javax.annotation-api", "1.3.2") {
because("Dual-licensed under CDDL 1.1 and GPL v2 with classpath exception.")
}

// Streaming API for XML (StAX)
allowDependency("javax.xml.stream", "stax-api", "1.0-2") {
because("Dual-licensed under CDDL 1.0 and GPL v3.")
}

// ANTLR 4
allowDependency("org.antlr", "antlr4-runtime", "4.9.1") {
because("BSD 3-clause. http://www.antlr.org/license.html")
}

// JSON-P https://javaee.github.io/jsonp/
allowDependency("org.glassfish", "javax.json", "1.1.4") {
because(
"Dual-licensed under CDDL 1.1 and GPL v2 with classpath exception. https://oss.oracle.com/licenses/CDDL+GPL-1.1"
)
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion catalog/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ dependencies {

implementation(Dependencies.Androidx.appCompat)
implementation(Dependencies.Androidx.constraintLayout)
implementation(Dependencies.Androidx.coreKtx)
implementation(Dependencies.Androidx.fragmentKtx)
implementation(Dependencies.material)
implementation(Dependencies.Kotlin.androidxCoreKtx)
implementation(Dependencies.Kotlin.stdlib)
implementation(Dependencies.Navigation.navFragmentKtx)
implementation(Dependencies.Navigation.navUiKtx)
Expand Down
2 changes: 1 addition & 1 deletion datacapture/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,13 @@ dependencies {
coreLibraryDesugaring(Dependencies.desugarJdkLibs)

implementation(Dependencies.Androidx.appCompat)
implementation(Dependencies.Androidx.coreKtx)
implementation(Dependencies.Androidx.fragmentKtx)
implementation(Dependencies.HapiFhir.validation) {
exclude(module = "commons-logging")
exclude(module = "httpclient")
exclude(group = "net.sf.saxon", module = "Saxon-HE")
}
implementation(Dependencies.Kotlin.androidxCoreKtx)
implementation(Dependencies.Kotlin.kotlinTestJunit)
implementation(Dependencies.Kotlin.stdlib)
implementation(Dependencies.Lifecycle.viewModelKtx)
Expand Down
72 changes: 71 additions & 1 deletion workflow/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ createJacocoTestReportTask()

android {
compileSdk = Sdk.compileSdk
buildToolsVersion = Plugins.Versions.buildTools

defaultConfig {
minSdk = Sdk.minSdk
targetSdk = Sdk.targetSdk
Expand All @@ -49,6 +51,8 @@ android {
multiDexEnabled = true
}

sourceSets { getByName("test").apply { resources.setSrcDirs(listOf("testdata")) } }

buildTypes {
getByName("release") {
isMinifyEnabled = false
Expand All @@ -66,23 +70,89 @@ android {
targetCompatibility = JavaVersion.VERSION_1_8
}

packagingOptions {
resources.excludes.addAll(
listOf(
"license.html",
"META-INF/ASL2.0",
"META-INF/ASL-2.0.txt",
"META-INF/DEPENDENCIES",
"META-INF/LGPL-3.0.txt",
"META-INF/LICENSE",
"META-INF/LICENSE.txt",
"META-INF/license.txt",
"META-INF/license.html",
"META-INF/LICENSE.md",
"META-INF/NOTICE",
"META-INF/NOTICE.txt",
"META-INF/NOTICE.md",
"META-INF/notice.txt",
"META-INF/LGPL-3.0.txt",
"META-INF/sun-jaxb.episode",
"META-INF/sun-jaxb.episode",
"META-INF/*.kotlin_module",
"readme.html",
)
)
}

// See https://developer.android.com/studio/write/java8-support
kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8.toString() }

configureJacocoTestOptions()
}

configurations {
all {
exclude(module = "json")
exclude(module = "xpp3")
exclude(module = "hamcrest-all")
exclude(module = "javax.activation")
exclude(group = "org.apache.httpcomponents")
exclude(module = "activation", group = "javax.activation")
exclude(module = "javaee-api", group = "javax")
exclude(module = "hamcrest-all")
exclude(module = "javax.activation")
exclude(group = "xml-apis")
exclude(group = "org.eclipse.persistence")
exclude(group = "com.google.code.javaparser")
exclude(group = "jakarta.activation")
// exclude(group = "jakarta.xml.bind")
}
}

dependencies {
androidTestImplementation(Dependencies.AndroidxTest.core)
androidTestImplementation(Dependencies.AndroidxTest.extJunit)
androidTestImplementation(Dependencies.AndroidxTest.extJunitKtx)
androidTestImplementation(Dependencies.AndroidxTest.runner)
androidTestImplementation(Dependencies.AndroidxTest.workTestingRuntimeKtx)
androidTestImplementation(Dependencies.junit)
androidTestImplementation(Dependencies.truth)

api(Dependencies.HapiFhir.structuresR4) { exclude(module = "junit") }

coreLibraryDesugaring(Dependencies.desugarJdkLibs)

implementation(Dependencies.Kotlin.androidxCoreKtx)
implementation(Dependencies.Androidx.coreKtx)
implementation(Dependencies.Cql.evaluator)
implementation(Dependencies.Cql.evaluatorBuilder)
implementation(Dependencies.Cql.evaluatorDagger)
implementation(Dependencies.Jackson.annotations)
implementation(Dependencies.Jackson.core)
implementation(Dependencies.Jackson.databind)
implementation(Dependencies.JavaJsonTools.jacksonCoreUtils)
implementation(Dependencies.JavaJsonTools.msgSimple)
implementation(Dependencies.Kotlin.kotlinCoroutinesAndroid)
implementation(Dependencies.Kotlin.kotlinCoroutinesCore)
implementation(Dependencies.Kotlin.stdlib)
implementation(Dependencies.stax)
implementation(Dependencies.woodstox)
implementation(Dependencies.xerces)
implementation(project(":engine"))

testImplementation(Dependencies.AndroidxTest.core)
testImplementation(Dependencies.junit)
testImplementation(Dependencies.robolectric)
testImplementation(Dependencies.truth)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.android.fhir.workflow

import com.google.android.fhir.FhirEngine
import com.google.android.fhir.search.search
import kotlinx.coroutines.runBlocking
import org.hl7.fhir.instance.model.api.IBaseResource
import org.hl7.fhir.instance.model.api.IIdType
import org.hl7.fhir.r4.model.Library
import org.hl7.fhir.r4.model.Measure
import org.hl7.fhir.r4.model.Patient
import org.opencds.cqf.cql.evaluator.fhir.dal.FhirDal

class FhirEngineDal(private val fhirEngine: FhirEngine) : FhirDal {
val libs = mutableMapOf<String, Library>()

override fun read(id: IIdType?): IBaseResource {
TODO("Not yet implemented")
}

override fun create(resource: IBaseResource?) {
TODO("Not yet implemented")
}

override fun update(resource: IBaseResource?) {
TODO("Not yet implemented")
}

override fun delete(id: IIdType?) {
TODO("Not yet implemented")
}

override fun search(resourceType: String?): MutableIterable<IBaseResource> {
return runBlocking {
when (resourceType) {
"Patient" -> fhirEngine.search<Patient> {}.toMutableList()
else -> throw NotImplementedError("Not yet implemented")
}
}
}

override fun searchByUrl(resourceType: String?, url: String?): MutableIterable<IBaseResource> {
return runBlocking {
when (resourceType) {
"Measure" -> fhirEngine.search<Measure> { filter(Measure.URL, { value = url }) }
"Library" -> listOf(libs[url] as Library)
else -> listOf()
}.toMutableList()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@

package com.google.android.fhir.workflow

import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.hl7.elm.r1.VersionedIdentifier
import org.hl7.fhir.instance.model.api.IBaseResource
import org.hl7.fhir.r4.model.Library
import org.opencds.cqf.cql.evaluator.cql2elm.content.fhir.BaseFhirLibraryContentProvider
import org.opencds.cqf.cql.evaluator.fhir.adapter.r4.AdapterFactory

/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertThat(4 as Int).isEqualTo(2 + 2)
class FhirEngineLibraryContentProvider(adapterFactory: AdapterFactory) :
BaseFhirLibraryContentProvider(adapterFactory) {
val libs = mutableMapOf<String, Library>()

override fun getLibrary(libraryIdentifier: VersionedIdentifier): IBaseResource {
return libs[libraryIdentifier.id]!!
}
}
Loading

0 comments on commit 61f774d

Please sign in to comment.