From 4122bc97d473ecb29f8d9fe7fd6ca9b17b7713ab Mon Sep 17 00:00:00 2001 From: Michael Vorburger Date: Thu, 16 May 2024 11:10:49 +0200 Subject: [PATCH 1/9] Update CODEOWNERS to assign listed individuals instead of group as reviewers of PRs (#2545) This initial list matches https://github.com/orgs/google/teams/android-fhir-reviewers. We were not able to get @google/android-fhir-reviewers working; see https://github.com/google/android-fhir/pull/2536 for background. See https://github.com/google/android-fhir/issues/2320 for overall motivation. --- CODEOWNERS | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/CODEOWNERS b/CODEOWNERS index 63cd139dc3..512f12d413 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,2 +1,14 @@ -# Owners of the repository -* @google/android-fhir @santosh-pingle +# This file lists people who get automatically added as Reviewers for Pull Requests. +# +# Note that we intentionally do NOT just include all committers here by using @google/android-fhir, +# nor were we able to get it working using a group such as @google/android-fhir-reviewers; +# details about why are described on https://github.com/google/android-fhir/issues/2320 +# and https://github.com/google/android-fhir/pull/2536. +# +# See https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners + +# These people for *ALL* Pull Requests: +* @aditya-07 @jingtang10 @MJ1998 @santosh-pingle + +# These for anything documentation related: +docs/* @vorburger From b1e6111aaa8e563fdc383368af8a068f836db6e8 Mon Sep 17 00:00:00 2001 From: Michael Vorburger Date: Tue, 21 May 2024 17:46:54 +0200 Subject: [PATCH 2/9] Migrate Wiki to Docs (#2546) Co-authored-by: Madhuram Jajoo --- .github/PULL_REQUEST_TEMPLATE.md | 5 +- .vscode/settings.json | 20 +- Contributing.md | 2 +- README.md | 22 +- docs/contrib/dependencies.md | 5 + docs/contrib/index.md | 326 +++++++++ docs/contrib/roadmap.md | 45 ++ docs/faq.md | 93 +++ docs/index.md | 34 + docs/use/Extensions.md | 5 + docs/use/FEL/Demo-app.md | 15 + .../FEL/FHIR-search-specification-support.md | 49 ++ docs/use/FEL/Getting-started.md | 64 ++ docs/use/FEL/Manage-FHIR-resources-locally.md | 74 +++ docs/use/FEL/Privacy-Security.md | 27 + docs/use/FEL/Search-FHIR-resources.md | 456 +++++++++++++ docs/use/FEL/Sync-data-with-FHIR-server.md | 172 +++++ docs/use/FEL/fhir-engine-components.png | Bin 0 -> 32754 bytes docs/use/FEL/index.md | 29 + docs/use/SDCL/Author-questionnaires.md | 625 ++++++++++++++++++ ...tomize-how-a-Questionnaire-is-displayed.md | 133 ++++ docs/use/SDCL/Demo-app.md | 11 + docs/use/SDCL/FHIR-specification-support.md | 213 ++++++ docs/use/SDCL/Getting-Started.md | 179 +++++ docs/use/SDCL/Reference-external-data.md | 33 + docs/use/SDCL/Use-QuestionnaireFragment.md | 181 +++++ .../Use-QuestionnaireResponseValidator.md | 7 + docs/use/SDCL/Use-ResourceMapper.md | 157 +++++ docs/use/SDCL/index.md | 30 + docs/use/SDCL/sdc-lib-intro-1.png | Bin 0 -> 41781 bytes docs/use/SDCL/sdc-lib-intro-2.png | Bin 0 -> 40980 bytes docs/use/SDCL/sdc-lib-workflow.png | Bin 0 -> 186807 bytes docs/use/SDCL/sdc-ref-dropdown.png | Bin 0 -> 49943 bytes docs/use/WFL/Compile-and-Execute-CQL.md | 127 ++++ docs/use/WFL/Evaluate-a-Library.md | 78 +++ docs/use/WFL/Evaluate-a-Measure.md | 229 +++++++ docs/use/WFL/Generate-A-Care-Plan.md | 171 +++++ docs/use/WFL/Getting-Started.md | 124 ++++ docs/use/WFL/index.md | 28 + mkdocs.yaml | 65 +- 40 files changed, 3806 insertions(+), 28 deletions(-) create mode 100644 docs/contrib/dependencies.md create mode 100644 docs/contrib/index.md create mode 100644 docs/contrib/roadmap.md create mode 100644 docs/faq.md create mode 100644 docs/use/Extensions.md create mode 100644 docs/use/FEL/Demo-app.md create mode 100644 docs/use/FEL/FHIR-search-specification-support.md create mode 100644 docs/use/FEL/Getting-started.md create mode 100644 docs/use/FEL/Manage-FHIR-resources-locally.md create mode 100644 docs/use/FEL/Privacy-Security.md create mode 100644 docs/use/FEL/Search-FHIR-resources.md create mode 100644 docs/use/FEL/Sync-data-with-FHIR-server.md create mode 100644 docs/use/FEL/fhir-engine-components.png create mode 100644 docs/use/FEL/index.md create mode 100644 docs/use/SDCL/Author-questionnaires.md create mode 100644 docs/use/SDCL/Customize-how-a-Questionnaire-is-displayed.md create mode 100644 docs/use/SDCL/Demo-app.md create mode 100644 docs/use/SDCL/FHIR-specification-support.md create mode 100644 docs/use/SDCL/Getting-Started.md create mode 100644 docs/use/SDCL/Reference-external-data.md create mode 100644 docs/use/SDCL/Use-QuestionnaireFragment.md create mode 100644 docs/use/SDCL/Use-QuestionnaireResponseValidator.md create mode 100644 docs/use/SDCL/Use-ResourceMapper.md create mode 100644 docs/use/SDCL/index.md create mode 100644 docs/use/SDCL/sdc-lib-intro-1.png create mode 100644 docs/use/SDCL/sdc-lib-intro-2.png create mode 100644 docs/use/SDCL/sdc-lib-workflow.png create mode 100644 docs/use/SDCL/sdc-ref-dropdown.png create mode 100644 docs/use/WFL/Compile-and-Execute-CQL.md create mode 100644 docs/use/WFL/Evaluate-a-Library.md create mode 100644 docs/use/WFL/Evaluate-a-Measure.md create mode 100644 docs/use/WFL/Generate-A-Care-Plan.md create mode 100644 docs/use/WFL/Getting-Started.md create mode 100644 docs/use/WFL/index.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 42a3912d35..a14d5aea50 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,7 +3,7 @@ Fixes #[issue number] **Description** -Clear and concise code change description. +Clear and concise code change description. **Alternative(s) considered** Have you considered any alternatives? And if so, why have you chosen the approach in this PR? @@ -14,8 +14,9 @@ Choose one: (Bug fix | Feature | Documentation | Testing | Code health | Builds **Screenshots (if applicable)** **Checklist** + - [ ] I have read and acknowledged the [Code of conduct](https://github.com/google/android-fhir/blob/master/CODE_OF_CONDUCT.md). -- [ ] I have read the [Contributing](https://github.com/google/android-fhir/wiki/Contributing) page. +- [ ] I have read the [Contributing](https://google.github.io/android-fhir/contrib/) page. - [ ] I have signed the Google [Individual CLA](https://cla.developers.google.com/about/google-individual), or I am covered by my company's [Corporate CLA](https://cla.developers.google.com/about/google-corporate ). - [ ] I have discussed my proposed solution with code owners in the linked issue(s) and we have agreed upon the general approach. - [ ] I have run `./gradlew spotlessApply` and `./gradlew spotlessCheck` to check my code follows the style guide of this project. diff --git a/.vscode/settings.json b/.vscode/settings.json index 72d2c0e6fa..ecbb75f88f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,12 @@ { + "editor.autoIndent": "advanced", + "editor.insertSpaces": true, + "editor.indentSize": "tabSize", + "editor.tabSize": 2, + + "files.insertFinalNewline": true, + "files.trimTrailingWhitespace": true, + // https://squidfunk.github.io/mkdocs-material/creating-your-site/ "yaml.schemas": { "https://squidfunk.github.io/mkdocs-material/schema.json": "mkdocs.yaml" @@ -10,5 +18,15 @@ "tag:yaml.org,2002:python/name:material.extensions.emoji.to_svg", "tag:yaml.org,2002:python/name:material.extensions.emoji.twemoji", "tag:yaml.org,2002:python/name:pymdownx.superfences.fence_code_format" - ] + ], + + "[yaml]": { + "editor.defaultFormatter": "redhat.vscode-yaml", + "diffEditor.ignoreTrimWhitespace": false, + "editor.quickSuggestions": { + "other": true, + "comments": false, + "strings": true + } + } } diff --git a/Contributing.md b/Contributing.md index 0e44bff587..3ecbcc7cc2 100644 --- a/Contributing.md +++ b/Contributing.md @@ -22,7 +22,7 @@ use GitHub pull requests for this purpose. Consult [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more information on using pull requests. -See [Developer's Guide](https://github.com/google/android-fhir/wiki/Developer's-Guide) for more information. +See [Contributor's Guide](https://google.github.io/android-fhir/contrib/) for more information. ## Community Guidelines diff --git a/README.md b/README.md index 5f21cf67c0..92eca3ea97 100644 --- a/README.md +++ b/README.md @@ -11,20 +11,20 @@ mobile applications. The SDK contains the following libraries: -| Library | Latest release | Code | Wiki | Min SDK | Summary | +| Library | Latest release | Code | Docs | Min SDK | Summary | | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Data Capture Library | [![Google Maven](https://badgen.net/maven/v/metadata-url/dl.google.com/dl/android/maven2/com/google/android/fhir/data-capture/maven-metadata.xml)](https://maven.google.com/web/index.html?#com.google.android.fhir:data-capture) | [code](https://github.com/google/android-fhir/tree/master/datacapture)| [wiki](https://github.com/google/android-fhir/wiki/Structured-Data-Capture-Library) | Android 7.0 (API level 24) | Collect, validate, and process healthcare data on Android | -| FHIR Engine Library | [![Google Maven](https://badgen.net/maven/v/metadata-url/dl.google.com/dl/android/maven2/com/google/android/fhir/engine/maven-metadata.xml)](https://maven.google.com/web/index.html?#com.google.android.fhir:engine) | [code](https://github.com/google/android-fhir/tree/master/engine) | [wiki](https://github.com/google/android-fhir/wiki/FHIR-Engine-Library) | Android 7.0 (API level 24) | Store and manage FHIR resources locally on Android and synchronize with FHIR server | -| Workflow Library | [![Google Maven](https://badgen.net/maven/v/metadata-url/dl.google.com/dl/android/maven2/com/google/android/fhir/workflow/maven-metadata.xml)](https://maven.google.com/web/index.html?#com.google.android.fhir:workflow) | [code](https://github.com/google/android-fhir/tree/master/workflow) | [wiki](https://github.com/google/android-fhir/wiki/Workflow-Library) | Android 7.0 (API level 24) | Provide decision support and analytics in clinical workflow on Android including implementation of specific FHIR operations ($measure_evaluate and $apply) | +| Data Capture Library | [![Google Maven](https://badgen.net/maven/v/metadata-url/dl.google.com/dl/android/maven2/com/google/android/fhir/data-capture/maven-metadata.xml)](https://maven.google.com/web/index.html?#com.google.android.fhir:data-capture) | [code](https://github.com/google/android-fhir/tree/master/datacapture)| [docs](https://google.github.io/android-fhir/use/SDCL/) | Android 7.0 (API level 24) | Collect, validate, and process healthcare data on Android | +| FHIR Engine Library | [![Google Maven](https://badgen.net/maven/v/metadata-url/dl.google.com/dl/android/maven2/com/google/android/fhir/engine/maven-metadata.xml)](https://maven.google.com/web/index.html?#com.google.android.fhir:engine) | [code](https://github.com/google/android-fhir/tree/master/engine) | [docs](https://google.github.io/android-fhir/use/FEL/) | Android 7.0 (API level 24) | Store and manage FHIR resources locally on Android and synchronize with FHIR server | +| Workflow Library | [![Google Maven](https://badgen.net/maven/v/metadata-url/dl.google.com/dl/android/maven2/com/google/android/fhir/workflow/maven-metadata.xml)](https://maven.google.com/web/index.html?#com.google.android.fhir:workflow) | [code](https://github.com/google/android-fhir/tree/master/workflow) | [docs](https://google.github.io/android-fhir/use/WFL/) | Android 7.0 (API level 24) | Provide decision support and analytics in clinical workflow on Android including implementation of specific FHIR operations ($measure_evaluate and $apply) | ## Demo apps This repository also contains the following demo apps: -| Demo app | Code | Wiki | -| ----------------------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------- | -| FHIR Engine Demo App | [code](https://github.com/google/android-fhir/tree/master/demo) | [wiki](https://github.com/google/android-fhir/wiki/FHIR-Engine-Library#demo-app) | -| Structured Data Capture Catalog App | [code](https://github.com/google/android-fhir/tree/master/catalog) | [wiki](https://github.com/google/android-fhir/wiki/Structured-Data-Capture-Library#catalog-app) | +| Demo app | Code | Docs | +| ----------------------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------- | +| FHIR Engine Demo App | [code](https://github.com/google/android-fhir/tree/master/demo) | [docs](https://google.github.io/android-fhir/use/FEL/Demo-app/) | +| Structured Data Capture Catalog App | [code](https://github.com/google/android-fhir/tree/master/catalog) | [docs](https://google.github.io/android-fhir/use/SDCL/Demo-app/) | **These applications are provided for demo purposes only. Do NOT use in production.** @@ -32,7 +32,7 @@ This repository also contains the following demo apps: The development of the SDK began as a collaborative effort between Google, [The World Health Organization](https://www.who.int/), and [Ona](https://ona.io/). Since then, a consortium of application developers have been contributing to the project. -To contribute to the project, please see [Contributing](https://github.com/google/android-fhir/wiki/Contributing) to get started. +To contribute to the project, please see [Contributing](https://google.github.io/android-fhir/contrib/) to get started. ## Feedback and getting help @@ -40,12 +40,14 @@ You can create a [GitHub issue](https://github.com/google/android-fhir/issues) f In case you find any security bug, please do NOT create a GitHub issue. Instead, email us at . -If you want to provide any feedback or discuss use cases you can: +If you want to provide any feedback or discuss use cases you can: + * email us at * start a [GitHub discussion](https://github.com/google/android-fhir/discussions) * start a new topic in [android](https://chat.fhir.org/#narrow/stream/276344-android), [questionnaire](https://chat.fhir.org/#narrow/stream/179255-questionnaire), [implementers](https://chat.fhir.org/#narrow/stream/179166-implementers), or [WHO SMART guidelines](https://chat.fhir.org/#narrow/stream/310477-who-smart-guidelines) stream in the [FHIR Zulip chat](https://chat.fhir.org/) ## Disclaimer + This product is not intended to be a medical device. HL7®, and FHIR® are the registered trademarks of Health Level Seven International and their use of diff --git a/docs/contrib/dependencies.md b/docs/contrib/dependencies.md new file mode 100644 index 0000000000..8d00d9d037 --- /dev/null +++ b/docs/contrib/dependencies.md @@ -0,0 +1,5 @@ +# External Dependencies + +This Android FHIR SDK uses a number of external libraries. + +Their exact version numbers are shown on [the Dependency Graph Insights](https://github.com/google/android-fhir/network/dependencies), which is automatically updated. diff --git a/docs/contrib/index.md b/docs/contrib/index.md new file mode 100644 index 0000000000..2dde9bbe0c --- /dev/null +++ b/docs/contrib/index.md @@ -0,0 +1,326 @@ +# Setup + +## Android Studio + +Use Android Studio 4.2+. + +## Node.js + +Install Node.js (e.g. [via package manager](https://nodejs.org/en/download/package-manager/)) which is needed for the `prettier` plugin we use to format `XML` files. + +## Kotlin style + +The codebase follows [google-java-format](https://github.com/google/google-java-format) instead of the [Kotlin coding conventions](https://kotlinlang.org/docs/coding-conventions.html) because google-java-format is strict and deterministic, and therefore removes formatting as a concern for developers altogether. + +If you would like Android Studio to help format your code, follow these steps to set up your Android Studio: + +1. Install and configure the [ktfmt plugin](https://github.com/facebookincubator/ktfmt) in Android Studio by following these steps: + 1. Go to Android Studio's `Settings` (or `Preferences`), select the `Plugins` category, click the `Marketplace` tab, search for the `ktfmt` plugin, and click the `Install` button + 1. In Android Studio's `Settings` (or `Preferences`), go to `Editor` → `ktfmt Settings`, tick `Enable ktfmt`, change the `Code style` to `Google (Internal)`, and click `OK` +1. Indent 2 spaces. In Android Studio's `Settings` (or `Preferences`), go to `Editor` → `Code Style` → `Kotlin` → `Tabs and Indents`, set `Tab size`, `Indent` and `Continuation indent` to `2`, and click `OK`. +1. Use single name import sorted lexigraphically. In Android Studio's `Settings` (or `Preferences`), go to `Editor` → `Code Style` → `Kotlin` → `Imports`, in `Top-level Symbols` and `Java statics and Enum Members` sections select `Use single name import` option, remove all the rules in `Packages to Use Imports with '*'` and `Import Layout` sections and click `OK`. + +Now you can go to `Code` → `Reformat code`, or press `Ctrl+Alt+L` (`⌘+⌥+L` for Mac) to automatically format code in Android Studio. + +Note that you don't have to do any of these. You could rely on spotless to format any code you want to push. For details see below. + +## XML style + +We use [prettier](https://prettier.io/)'s [XML plugin](https://github.com/prettier/plugin-xml) to format the XML code. At the moment we have not discovered an Android Studio style configuration that would produce the same result. As a result, please run `./gradlew spotlessApply` to format the XML files. + +# Development + +## Common Library + +The _common_ library module contains code that is shared across other modules e.g. _engine, datacapture_ . During development you might want to make updates to the _common_ module and test them on the dependant library. + +To make developing/testing these type of updates more efficient, it is recommended to replace the `implementation(Dependencies.androidFhirCommon)` dependency configuration with `implementation(project(":common"))` in the `build.gradle.kts` file. Then once the PR with the changes to _common_ is merged in and the artifact published, you can revert. + +Remember to update the `Versions.androidFhirCommon` variable with the correct/new version of the published artifact in the `Dependencies.kt` file + +# Testing + +## Unit Tests + +### Naming Conventions + +We follow the following naming convention for our test cases: + +``` +methodName_conditionUnderTest_expectedBehavior +``` + +For example: + +``` +isNumberEven_one_shouldReturnFalse +isNumberEven_two_shouldReturnTrue +``` + +## Instrumentation Tests + +### UI Automation Testing + +**For UI automation, “Page object framework” is used, Below is the structure of framework:** + +**Structure:** + +**Pages:** +Here all screens objects ,identifiers and functions are defined + +**Tests:** +All tests for all screens are written here + +**Testdata:** +Data which is used for testing mentioned here + +**Setup QA tests:** + +Precondition: + +1. To launch App and its activity create file under tests folder(Right click pages->New -> Kotlin class/File(BaseTest): + + ``` +open class BaseTest { + @get:Rule + val activityRule: ActivityScenarioRule = + ActivityScenarioRule(MainActivity::class.java) +} +``` + +Write testcase: + +1. Right click pages->New -> Kotlin class/File(AddPatientPage.kt) +2. On newly created file, objects ,identifiers and functions can be defined +3. Define object and identifiers as below: + +``` +private val pageName = "Add Patient" +private val addPatientButton = R.id.add_patient +``` + +4. To write functions: + +``` +fun validate_page() { + +} +``` + +5. To write verification of text + +``` +onView(allOf(withText(R.string.add_patient), withText(pageName))).check(matches(isDisplayed())) +``` + +6. To create Tests page for writing tests same as mentioned in step 1 (AddPatientTest.kt) +7. To access function from (AddPatientPage.kt), create its object: + +``` +class AddPatientTest() : BaseTest() { +private val addPatientPage: AddPatientPage = AddPatientPage() +} +``` + +8. Access function through object: + +``` +fun shouldBeAbleToValidatePage() { +addPatientPage.validate_page() +} +``` + +9. To run tests: + +precondition: +device or emulator should be connected + +Right click on test file created in step 6 -> Run 'AddPatientTest' + +### Screenshot Testing + +**To write Screenshot Tests**: + +1. To Launch Activity: + +``` +@get:Rule var activityTestRule = ActivityTestRule(MainActivity::class.java, false, false) + + val grantPermissionRule: GrantPermissionRule = + GrantPermissionRule.grant( + android.Manifest.permission.READ_EXTERNAL_STORAGE, + android.Manifest.permission.WRITE_EXTERNAL_STORAGE + ) +``` + +2. To write functions: + +``` +fun testScreenshotEntireActivity() { + +} +``` + +3. Launch activity through "activityrule": + +`val activity = activityTestRule.launchActivity(null)) +` + +4. get view of element: + +` +val view = activityTestRule.activity.findViewById(R.id.search_src_text) +` + +5. Record view through snapactivity: + +` +snapActivity(activity).setName("Registered Patient List").record() +` + +6. You can set name to the view and record that view: + +` +snap(view).setName("sample_view_test").record() +` + +**To Run Screenshot Tasks below:** + +`cleanScreenshots` - Clean last generated screenshot report + +`pullScreenshots` - Pull screenshots from your device + +`recordScreenshotTest` - Installs and runs screenshot tests, then records their output for later verification + +`runScreenshotTest` - Installs and runs screenshot tests, then generates a report + +`verifyScreenshotTest` - Installs and runs screenshot tests, then verifies their output against previously recorded screenshots + +**To run through ./gradlew below is the command:** + +`$ ./gradlew runDebugAndroidTestScreenshotTest` + +To run screenshot test for specific application: + +`$ ./gradlew Demo:runDebugAndroidTestScreenshotTest` + +**To directory run screenshot test using android studio:** + + Right click either the test folder or the test file in Android Studio and click 'Run Tests in ...': + +## Spotless + +We use Spotless to maintain the Java/Kotlin coding style in the codebase. Run the following command to check the codebase: + +``` +./gradlew spotlessCheck +``` + +and run the following command to apply fixes to the violations: + +``` +./gradlew spotlessApply +``` + +## License Headers + +Spotless maintains the license headers for Kotlin files. Use addlicense to maintain license headers in other files: + +``` +addlicense -c "Google LLC" -l apache . +``` + +## Jacoco Test Report + +### Run locally + +To run the task locally: + +``` +$./gradlew jacocoTestReport +``` + +To run the task locally for a specific module: + +``` +$./gradlew ::jacocoTestReport +``` + +The Jacoco test coverage report will be in the folder `/build/reports/jacoco/jacocoTestReport`. + +## Ruler + +We use [Ruler](https://github.com/spotify/ruler) to generate reports on the APK size of our demo/catalog app. This allows us to track increases in our SDK's library size. + +To generate these reports, run the `analyzeReleaseBundle` task on the project you are interested in. For example: + +``` +./gradlew :demo:analyzeReleaseBundle +``` + +The task will print a path to an HTML report, which is human-readable, and a JSON report, which can be used for automation. + +# Code Reviews + +PRs can only be merged if all of the following requirements are met: + +* Require approval from [code owners](https://github.com/google/android-fhir/blob/master/CODEOWNERS) +* Require status checks to pass before merging +* Require branches to be up to date before merging + +# Use unreleased GitHub build (for development/testing only) + +Each GitHub build of the project also contains a maven repository. You can access unreleased features by downloading it and including it in your project. To acquire the maven repository, go the the [actions](https://github.com/google/android-fhir/actions) page, and click on the build you want. In the build `artifacts` dropdown, you will find a `maven-repository.zip` file. After downloading and extracting it to a local folder, you can add it to your gradle setup via: + +``` +repositories { + maven { + url "file:///" + } +} +``` + +These artifacts are versioned as a combination of the current version + buildid (e.g. `0.1.0-alpha01-build_123`). You can find the version in the zip file by checking the contents of it and update your build file to match that version. + +# Common build problems + +1. Build failed java heap space + + Set `org.gradle.jvmargs=-Xmx2048m` in project gradle.properties . If it still fails you can further increase the memory. + +2. More than one file was found with OS independent path 'mozilla/public-suffix-list.txt'. + + Add this line to the packagingOptions in the build.gradle of you app + + `packagingOptions { + exclude 'mozilla/public-suffix-list.txt' + }` + +=== + +naming convention for view snake_case + +how to run tests + +# Working with libraries + +This section defines the process one goes through when making changes to any of the dependent libraries on the FHIR SDK. An example of a library is the [Workflow Library](../use/WFL/index.md). + +**Step 1:** + +* Make changes, updates, edits on the library's codebase.
+* Make sure to update the [Releases.kt](https://github.com/google/android-fhir/blob/master/buildSrc/src/main/kotlin/Releases.kt) configuration file with a new _Version/Artifact ID_ + +**Step 2:** + +* Make a PR (pull request) with the above changes, request a code review + +**Step 3:** + +* When PR is reviewed and merged - request for the artifact to be published on maven + +**Step 4:** + +* Update your/any dependent PR (PR using the library) with the new _Artifact ID_ and make/trigger the CI + +**NB:** For a specific example on working with FHIR SDK's Common Library during development, see [Common Library](#common-library). diff --git a/docs/contrib/roadmap.md b/docs/contrib/roadmap.md new file mode 100644 index 0000000000..f4f5785846 --- /dev/null +++ b/docs/contrib/roadmap.md @@ -0,0 +1,45 @@ +# Roadmap + +The [product roadmap board](https://github.com/google/android-fhir/projects/7) is where you can learn about what features are being working on, what stage they're in, and release timelines. Have any questions or comments about items on the roadmap or want to know how to get involved? Please use the [discussions section](https://github.com/google/android-fhir/discussions), or email us at . + +## Guide to the roadmap + +Every item pre-fixed with [Roadmap] relates to one or more issues on individual feature area project boards, with a label that indicates each of the following: + +* A **release phase** that describes the next expected phase of the roadmap item. See below for a guide to release phases. +* A **feature area** that indicates the specific library to which the item belongs. For a list of feature areas, see below. + +## Release phases + +Release phases indicate the stages that the product or feature goes through, from early testing to general availability. + +* **alpha**: Primarily for testing and feedback: Features still under heavy development, and subject to change. Not for production use, and no documentation provided. +* **beta**: Available in full or limited capacity: Features mostly complete and documented. +* **ga**: Generally available: Confidence within that community that this is ready for production use. Implementer able to provide support or leverage open source community + +Some features will be in exploratory stages, and have no timeframe available. These are included in the roadmap for early feedback. These are marked as follows: + +* **in design**: Feature in discovery phase. We have decided to build this feature, but are still figuring out how. +* **exploring**: Feature under consideration. We are considering building this feature, and gathering feedback on it or doing R&D. + +## Roadmap stages + +The roadmap is arranged on a [project board](https://github.com/google/android-fhir/projects/7) to give a sense for how far out each item is on the horizon (broken down by quarters). **This is just indicative at this stage and is subject to change**, especially further out on the timeline. There is also a specific column for exploratory R&D items where no current timeline has been decided. + +## Feature areas + +The SDK is designed in a modular fashion to enable developers to layer in a rich set of features for building FHIR capable mobile solutions. The feature areas, which are packaged as separate libraries are defined as follows: + +* **FHIR Engine:** includes APIs for managing FHIR resources (using FHIR protos), interacting with the storage layer (sqllite db), searching and syncing +* **Data Capture Library:** Implementation of the FHIR SDC specification for interacting with Questionnaires includes population and extraction +* **Workflow Library:** Provides specific operations for generating CarePlans and indicators relevant to implementers working with [WHO SMART Guidelines content](https://www.who.int/news/item/18-02-2021-from-paper-to-digital-pathway-who-launches-first-smart-guidelines) + +## Feedback and getting help + +Bugs and feature requests can be filed with [Github issues](https://github.com/google/android-fhir/issues). See the section on [How to Contribute](https://github.com/google/android-fhir/blob/master/docs/contributing.md) first + +If you want to provide any feedback or discuss use cases you can: + +* Email us at +* For general Android FHIR SDK discussion, join the FHIR Zulip chat for [Android](https://chat.fhir.org/#narrow/stream/276344-android) +* For WHO SMART Guidelines topics, see the FHIR Zulip chat for [WHO SMART Guidelines](https://chat.fhir.org/#narrow/stream/310477-who-smart-guidelines) diff --git a/docs/faq.md b/docs/faq.md new file mode 100644 index 0000000000..cfc1bb3faa --- /dev/null +++ b/docs/faq.md @@ -0,0 +1,93 @@ +# FAQs + +1. [What is the Android FHIR SDK?](#what-is-the-android-fhir-sdk) +1. [What is FHIR?](#what-is-fhir) +1. [Why is a FHIR SDK needed? What problem does it solve?](#why-is-a-fhir-sdk-needed-what-problem-does-it-solve) +1. [What are the components of the FHIR SDK?](#what-are-the-components-of-the-fhir-sdk) +1. [What is Google’s role in this project?](#what-is-googles-role-in-this-project) +1. [Who else is involved?](#who-else-is-involved) +1. [What is in/out of scope of the FHIR SDK?](#what-is-inout-of-scope-of-the-fhir-sdk) +1. [Do I have control of the data collected using the SDK?](#do-i-have-control-of-the-data-collected-using-the-sdk) +1. [How is data encrypted?](#how-is-data-encrypted) +1. [How can I build cross-platform applications?](#how-can-i-build-cross-platform-applications) +1. [What applications currently use the SDK?](#what-applications-currently-use-the-sdk) +1. [How to do database inspect in the FHIR demo app?](#how-to-do-database-inspect-in-the-fhir-demo-app) + +### What is the Android FHIR SDK? + +It is an open source library for Android developers who want to build [FHIR](http://hl7.org/fhir/)-enabled offline-capable, mobile-first healthcare applications. + +### What is FHIR? + +FHIR (Fast Healthcare Interoperability Resources) is the latest version of the HL7 standard for building modern patient centered healthcare applications - see [HL7 FHIR Specification](http://hl7.org/fhir/) + +### Why is a FHIR SDK needed? What problem does it solve? + +Today there is no simple way to build a FHIR compliant app on Android that is suited to the needs of LMICs - particularly offline capabilities due to poor connectivity. The FHIR SDK makes it easy for developers to build custom applications without needing to also build and maintain all the underlying components. + +### What are the components of the FHIR SDK? + +The SDK enables the common components that developers need to build rich, offline-capable, standard-compliant applications. This includes APIs for standard data capture, data access, search and sync as well as encrypted local storage (using SQLite DB). + +### What is Google’s role in this project? + +We are contributing to the design and development of the open source FHIR SDK + +### Who else is involved? + +The Android FHIR SDK project was initiated by the WHO together with teams from Android and [ONA](https://ona.io/home/). There is an open consortium of groups convened by the WHO to progress the design and development of the FHIR SDK as part of supporting their [SMART Guidelines work](https://www.who.int/teams/digital-health-and-innovation/smart-guidelineshttp:// "SMART Guidelines work"). To-date developers from ONA, IPRD and Argusoft as well as a number of independent software engineers have contributed to the code-base. It is an open source initiative and we welcome contributions from any developers who want to get involved. + +### What is in/out of scope of the FHIR SDK? + +In the SDK: + +* Implementation of the FHIR specification relevant for mobile health use cases +* Helper methods for common implementation scenarios that are implementer agnostic +* Encryption of data within the SQLite DB at rest (using standard Android encryption) + +Not in the SDK: + +* Custom implementation requirements: these should be in implementer specific libraries +* Creation of an Authenticated client: assume server side implementation with client side tokens. +* Authorization: rules around what resources a specific user should have access to are applied server side. + +### Do I have control of the data collected using the SDK? + +The Android FHIR SDK stores data on device in a SQLite database and can be configured to sync the data with a FHIR server specified by the application. The choice of storage (on-prem or cloud based) is up to the individual implementation. + +### How is data encrypted? + +Data in the SQLite database is **encrypted at rest** using standard Android device encryption (minimum support for Android 5.0). For devices using Android 6.0 or above, additional level of application based encryption is provided by SQLCipher integration. [Read more](use/FEL/Privacy-Security.md#database-encryption) + +There is no limitation on supporting **encryption in transit** and this is recommended best practice for all implementers to put in place when syncing data between the Android client and a FHIR server. + +### How can I build cross-platform applications? + +The Android FHIR SDK is designed for the Android OS. There are currently no plans to support iOS. + +### What applications currently use the SDK? + +We have an active community of developers that are in the process of building applications using the FHIR SDK. + +### How to do database inspect in the FHIR demo app? + +The data inside FHIR database are encrypted for safety reason. This is controlled by the flag `enableEncryptionIfSupported` flag in the `FhirEngineConfiguration`. To debug/inspect the database content(for example, in the demo app), developer can temporarily disable the encryption as following: +In [FhirApplication](https://github.com/google/android-fhir/blob/master/demo/src/main/java/com/google/android/fhir/demo/FhirApplication.kt), when initiate the `FhirEngineProvider`, set `enableEncryptionIfSupported` to false. Code example: + +```kotlin +class FhirApplication : Application() { + // Only initiate the FhirEngine when used for the first time, not when the app is created. + private val fhirEngine: FhirEngine by lazy { constructFhirEngine() } + + override fun onCreate() { + super.onCreate() + FhirEngineProvider.init( + FhirEngineConfiguration(enableEncryptionIfSupported = false, RECREATE_AT_OPEN) + ) + Sync.oneTimeSync(this) + } +``` + +In AndroidStudio, run the `demo` app on a connected android device. Then go to View -> Tool Windows -> App Inspection, click on the Database Inspector tab to inspect the database `resources.db`. + +One thing to note: If there is any database exception after disabling encryption, developers can wipe the demo app data either in Settings or via `adb shell pm clear com.google.android.fhir.demo`, and rerun the demo app. diff --git a/docs/index.md b/docs/index.md index d0edbd8e11..4ad39026ac 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,3 +4,37 @@ The Android FHIR SDK is a set of Kotlin libraries for building offline-capable, healthcare applications using the [HL7® FHIR® standard](https://www.hl7.org/fhir/) on Android. It aims to accelerate the adoption of FHIR by making it easy to incorporate FHIR into new and existing mobile applications. + +Use the following table for documentation and resources to get started with each library in the SDK. + +| Library | Latest release | Code | Docs | Codelab | Summary | +| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | - | +| Data Capture Library | [![Google Maven](https://badgen.net/maven/v/metadata-url/dl.google.com/dl/android/maven2/com/google/android/fhir/data-capture/maven-metadata.xml)](https://maven.google.com/web/index.html?#com.google.android.fhir:data-capture) | [code](https://github.com/google/android-fhir/tree/master/datacapture)| [docs](use/SDCL/index.md) | [codelab](https://github.com/google/android-fhir/tree/master/codelabs/datacapture) | Collects, validates, and processes healthcare data on Android | +| FHIR Engine Library | [![Google Maven](https://badgen.net/maven/v/metadata-url/dl.google.com/dl/android/maven2/com/google/android/fhir/engine/maven-metadata.xml)](https://maven.google.com/web/index.html?#com.google.android.fhir:engine) | [code](https://github.com/google/android-fhir/tree/master/engine) | [docs](use/FEL/index.md) | [codelab](https://github.com/google/android-fhir/tree/master/codelabs/engine) | Stores and manages FHIR resources locally on Android and synchronizes with FHIR server | +| Workflow Library | [![Google Maven](https://badgen.net/maven/v/metadata-url/dl.google.com/dl/android/maven2/com/google/android/fhir/workflow/maven-metadata.xml)](https://maven.google.com/web/index.html?#com.google.android.fhir:workflow) | [code](https://github.com/google/android-fhir/tree/master/workflow) | [docs](use/WFL/index.md) | | Provides decision support and analytics in clinical workflow on Android including implementation of specific FHIR operations ($measure_evaluate and $apply) | +| Knowledge Manager Library | [![Google Maven](https://badgen.net/maven/v/metadata-url/dl.google.com/dl/android/maven2/com/google/android/fhir/knowledge/maven-metadata.xml)](https://maven.google.com/web/index.html?#com.google.android.fhir:knowledge) | [code](https://github.com/google/android-fhir/tree/master/knowledge) | | | Manages knowledge resources locally on Android and supports other libraries with knowledge resources | + +## Project information + +* [Project roadmap](contrib/roadmap.md) +* [FAQs](faq.md) + +## Resources + +### FHIR and implementation guides + +* [HL7 FHIR](https://www.hl7.org/fhir/) +* [Structured Data Capture](http://hl7.org/fhir/us/sdc/) +* [Clinical Quality Lanugage (CQL)](https://cql.hl7.org/) + +### More on mobile health landscape + +* [Digital Health Atlas](https://digitalhealthatlas.org/) +* [Global Goods Guidebook](https://digitalsquare.org/global-goods-guidebook) + +### Community + +* [Zulip FHIR chat](https://chat.fhir.org/) has the following streams that are relevant to this codebase: + * [#android](https://chat.fhir.org/#narrow/stream/276344-android) + * [#implementers](https://chat.fhir.org/#narrow/stream/179166-implementers) + * [#questionnaire](https://chat.fhir.org/#narrow/stream/179255-questionnaire) for the SDC library and gallery diff --git a/docs/use/Extensions.md b/docs/use/Extensions.md new file mode 100644 index 0000000000..2d9e200de1 --- /dev/null +++ b/docs/use/Extensions.md @@ -0,0 +1,5 @@ +# FHIR Extensions + +This page lists [FHIR Extensions](http://hl7.org/fhir/extensibility.html) defined by the Android FHIR SDK. + +* UUID diff --git a/docs/use/FEL/Demo-app.md b/docs/use/FEL/Demo-app.md new file mode 100644 index 0000000000..4923791960 --- /dev/null +++ b/docs/use/FEL/Demo-app.md @@ -0,0 +1,15 @@ +# Demo App + +To demonstrate the capabilities of the FHIR Engine Library, we have created the *FHIR Engine Demo* app. + +To run this app in Android Studio, [create a run/debug configuration](https://developer.android.com/studio/run/rundebugconfig) for the `demo` module using the [Android App](https://developer.android.com/studio/run/rundebugconfig#android-application) template and run the app using the configuration. + +Alternatively, run the following command to build and install the debug APK on your device/emulator: + +```shell +./gradlew :demo:installDebug +``` + +The Demo app uses the [HAPI FHIR demo server](https://hapi.fhir.org/baseR4/) as the server to sync to and all data is visible to anyone on the internet. Do not use real data, or any data you would not want publicly visible. + +The app filters for patients with `Patient.address.city = NAIROBI`. If creating a new patient in the app, set the **City** field to `NAIROBI` for it to show up in the **Registered Patients** list. diff --git a/docs/use/FEL/FHIR-search-specification-support.md b/docs/use/FEL/FHIR-search-specification-support.md new file mode 100644 index 0000000000..101ab21bd1 --- /dev/null +++ b/docs/use/FEL/FHIR-search-specification-support.md @@ -0,0 +1,49 @@ +# FHIR search specification support + +This document tracks the support for the FHIR search specification supported by the SDK (fhirEngine library) and common example use cases. It will be updated over time. + +## Search parameter types + +The following table summarizes the support (released and planned) for [search parameter types](https://www.hl7.org/fhir/search.html) within the SDK: + +| | Support | Notes | +|-----------|-------------|--------------------------| +| String | Yes | | +| Number | Yes | | +| Date | Yes | | +| DateTime | Yes | | +| Token | Partial | URI, code, boolean | +| Reference | Yes | See examples | +| Quantity | No | Planned | +| Special | In-progress | TBC | +| Composite | Yes | AND and OR are supported | + +## Search prefixes + +https://www.hl7.org/fhir/search.html#prefix + +| | Support | Notes | +|----|---------|---------------------------| +| eq | Partial | Numerical and date values | +| ne | Partial | Numerical and date values | +| gt | Partial | Numerical and date values | +| lt | Partial | Numerical and date values | +| ge | Partial | Numerical and date values | +| le | Partial | Numerical and date values | +| sa | No | | +| eb | No | | +| ap | No | | + +## Modifiers + +https://www.hl7.org/fhir/search.html#modifiers + +| | Support | Notes | +|-----------------------------------------------|---------|--------| +| :contains | Partial | String | +| :exact | Partial | String | +| :missing, :text, :in, :below, :above, :not-in | No | | + +Other: + +* Search by meta-data - in-progress: https://github.com/google/android-fhir/issues/481 diff --git a/docs/use/FEL/Getting-started.md b/docs/use/FEL/Getting-started.md new file mode 100644 index 0000000000..2066f55254 --- /dev/null +++ b/docs/use/FEL/Getting-started.md @@ -0,0 +1,64 @@ +# Getting Started + +This page describes how to configure an Android Studio project to use the FHIR Engine Library, and simple examples of how to use the library. + +This guide is intended for developers who are familiar with basic Android development with Kotlin, and proficient in working with [FHIR](http://hl7.org/fhir/) concepts and resources. + +## Dependencies + +The FHIR Engine Library is available through [Google's Maven repository](https://maven.google.com/web/index.html), which should be already configured for Android projects created in Android Studio 3.0 and higher. + +Add the following dependency to your module's app-level `build.gradle` file, typically `app/build.gradle`: + +```kotlin +dependencies { + implementation("com.google.android.fhir:engine:0.1.0-beta02") +} +``` + +In the same file, add the following APK packaging options: + +```kotlin +android { + // ... + packagingOptions { + resources.excludes.addAll(listOf("META-INF/ASL-2.0.txt", "META-INF/LGPL-3.0.txt")) + } +} +``` + +The minimum API level supported is 24. The library also requires [Android Gradle Plugin](https://developer.android.com/studio/releases/gradle-plugin) +version 4.0.0 or later for [Java 8+ API desugaring support](https://developer.android.com/studio/write/java8-support#library-desugaring). + +### Initialize and get a FHIR Engine + +To use a FHIR Engine instance, first call `FhirEngineProvider.init()` with a `FhirEngineConfiguration`. This must be done only once; we recommend doing this in the `onCreate()` function of your `Application` class. + +```kotlin +class MyApplication : Application() { + override fun onCreate() { + super.onCreate() + + FhirEngineProvider.init( + FhirEngineConfiguration( + enableEncryptionIfSupported = true, + RECREATE_AT_OPEN + ) + ) + } +} +``` + +When you need to use a `FhirEngine`, make sure to call the method `FhirEngineProvider.getInstance(Context)`: + +```kotlin +val fhirEngine = FhirEngineProvider.getInstance(this) +``` + +See [FhirApplication](https://github.com/google/android-fhir/blob/master/demo/src/main/java/com/google/android/fhir/demo/FhirApplication.kt) in the demo app for a sample implementation. + +## Next steps + +* [Manage FHIR resources Locally](Manage-FHIR-resources-locally.md) +* [Search FHIR resources](Search-FHIR-resources.md) +* [Sync data with a FHIR server](Sync-data-with-FHIR-server.md) diff --git a/docs/use/FEL/Manage-FHIR-resources-locally.md b/docs/use/FEL/Manage-FHIR-resources-locally.md new file mode 100644 index 0000000000..4299d2977f --- /dev/null +++ b/docs/use/FEL/Manage-FHIR-resources-locally.md @@ -0,0 +1,74 @@ +# Manage FHIR Resources Locally + +The FHIR Engine Library has a CRUD-like interface for managing local FHIR resources. The FHIR resources are represented using [HAPI FHIR Structures](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-structures-r4/index.html) objects and types. + +**Note**: All FHIR Engine functions are `suspend` functions and must be called from a [coroutine](https://developer.android.com/kotlin/coroutines), which is not included in the examples below. + +## Create a FHIR resource + +A `FhirEngine` instance stores FHIR resources represented as [HAPI FHIR Structures](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-structures-r4/index.html) objects. To create a FHIR resource in a `FhirEngine` instance, first make the resource using the HAPI FHIR Structures API, then use `FhirEngine.create()`. + +**NOTE:** The FHIR Engine requires all stored resources to have a logical [`Resource.id`](https://www.hl7.org/fhir/resource-definitions.html#Resource.id). If the `id` is specified in the resource passed to `create()`, the resource created in `FhirEngine` will have the same `id`. If no `id` is specified, `FhirEngine` will generate a UUID as that resource's `id` and include it in the returned list of IDs. + +Example: Create a Patient resource + +```kotlin +// Create a new Patient resource +val patient = Patient().apply{ + id = "19682646" + gender = Enumerations.AdministrativeGender.MALE + addName( + HumanName().apply { + addGiven("Lance") + addGiven("Thomas") + family = "East" + } + ) +} + +// Create the resource in an existing FhirEngine instance +fhirEngine.create(patient) +``` + +## Read a FHIR Resource + +Read resources from FHIR Engine by providing the type and logical Resource ID. + +Example: Read a Patient resource + +```kotlin +// Read a Patient resource by ID +try { + val patient = fhirEngine.get("19682646") +} catch (e : ResourceNotFoundException) { + e.printStackTrace() +} +``` + +You can also [search for FHIR resources](Search-FHIR-resources.md). + +## Update a FHIR resource + +Example: Update a Patient resource + +```kotlin +val updatedPatient = patient.copy().setActive(false) + +fhirEngine.update(updatedPatient) + +``` + +## Delete a FHIR resource + +Example: Delete a Patient resource by ID. + +```kotlin +fhirEngine.delete("19682646") +``` + +If you already have a copy of the resource you want to delete, you can get the logical ID from it instead. + +```kotlin +fhirEngine.delete(patient.logicalId) + +``` diff --git a/docs/use/FEL/Privacy-Security.md b/docs/use/FEL/Privacy-Security.md new file mode 100644 index 0000000000..a7500928f0 --- /dev/null +++ b/docs/use/FEL/Privacy-Security.md @@ -0,0 +1,27 @@ +# Privacy & Security + +## Database encryption + +In FHIREngine, by default, we utilize Android [encryption](https://source.android.com/security/encryption) and support Android 5.0 and above. This ensures data is always encrypted at rest. + +On Android 6.0 or above, FHIREngine offers **additional** application level database encryption via SQLChiper. + +To enable database encryption, you should invoke the `FhirEngineProvider#init(FhirEngineConfiguration)` in your `Application#onCreate` before creating any instance of `FhirEngine`. You can select one of the two database error handlings: + +* `UNSPECIFIED`: All database errors will be propagated to the call site. The caller shall handle the database error on a case-by-case basis. +* `RECREATE_AT_OPEN`: If a database error occurs at open, automatically recreate the database. This strategy is **NOT** respected when opening a previously unencrypted database with an encrypted configuration or vice versa. An `IllegalStateException` is thrown instead. + +Here is a code snippet of enabling database encryption with `RECREATE_AT_OPEN` error handling strategy: + +``` +FhirEngineProvider.init( + FhirEngineConfiguration( + enableEncryptionIfSupported = true, + databaseErrorStrategy = RECREATE_AT_OPEN + ) +) +``` + +## Data safety + +This library does not collect or share any personal or sensitive [user data](https://developer.android.com/guide/topics/data/collect-share) with any third party libraries or SDKs. diff --git a/docs/use/FEL/Search-FHIR-resources.md b/docs/use/FEL/Search-FHIR-resources.md new file mode 100644 index 0000000000..37e467d12a --- /dev/null +++ b/docs/use/FEL/Search-FHIR-resources.md @@ -0,0 +1,456 @@ +# Search FHIR Resources + +You can search for resources in a FHIR Engine instance using the Android FHIR SDK's Search DSL or [FHIR search strings](https://www.hl7.org/fhir/search.html). The SDK supports [all defined search parameters](https://www.hl7.org/fhir/searchparameter-registry.html). + +See the full list of [FHIR search specification support](FHIR-search-specification-support.md). + +## Search using Search DSL + +The Search DSL is based on [FHIR search](https://www.hl7.org/fhir/search.html), and most of the capabilities of FHIR search have an equivalent in Search DSL. + +### General search syntax + +This is the simplest search syntax: + +```kotlin +val patients = fhirEngine.search {} +``` + +This search returns a `List` containing all `Patient` resources in the `FhirEngine` instance and is equivalent to the FHIR search: + +``` +GET [base]/Patient +``` + +If you're having trouble getting search to work, make sure Android Studio is using the correct version of `search`. + +![Search code completion](https://user-images.githubusercontent.com/7772901/197892131-38247b9a-9f3c-4dff-a2aa-f1019d8476d2.png) + +In most cases, use a `filter` to search for particular Patient resources. + +```kotlin +fhirEngine.search { + filter(Patient.GIVEN, { + value = "Kiran" + modifier = StringFilterModifier.MATCHES_EXACTLY + }) +} +``` + +To do so, first specify a search parameter from the HAPI FHIR resource being searched. For the example above, we recommend you use Android Studio's code completion by first entering the resource followed by a dot, such as `Patient.`, then pressing **ctrl+space** to see valid options. They will be of the type `XClientParam!`. + +Search parameter code completion + +Alternatively, look at the Field Summary for the [HAPI FHIR Patient resource](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/Patient.html) and find fields with the description "**Fluent Client** search parameter constant for **field**". These are the Patient resource fields we can search by. + +![HAPI FHIR Patient documentation](https://user-images.githubusercontent.com/7772901/197891914-4a5a0e23-ae28-408c-9602-8dcef5f28277.png) + +Not every field in a resource has search implemented, for example `Patient.maritalStatus` does not have a search parameter implemented in HAPI FHIR. On the other hand, HAPI FHIR provides some convenience search parameters like [`Patient.NAME`](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/Patient.html#NAME) which searches across all name-related fields but is not part of the base FHIR specification. + +Next, provide a `value` to search for. The expected type for the value for `value` depends on the type of the search parameter from the HAPI FHIR resource field, or seen in the code completion pop-up. In the example above, `Patient.GIVEN` is a `StringClientParam` so `value` should be a `String`. + +In addition, most parameter types have ways to control how the search is performed. In the case of `String` there is a `modifier` field. The `Number`, `Date`, and `Quantity` parameters have a `prefix` field instead, corresponding to the [FHIR Search prefix](https://www.hl7.org/fhir/search.html#prefix). + +For more details, see the examples below or [look at the implementation of the specific filter type](https://github.com/google/android-fhir/tree/master/engine/src/main/java/com/google/android/fhir/search/filter). + +### Using the OR operator + +By default, multiple filters are considered using logical `AND`. You can treat them as an `OR` by setting the `operation` field. The following example returns patients with a given name or family name of exactly "Jay". + +```kotlin +fhirEngine.search { + filter(Patient.GIVEN, { + value = "Jay" + modifier = StringFilterModifier.MATCHES_EXACTLY + }) + + filter(Patient.FAMILY, { + value = "Jay" + modifier = StringFilterModifier.MATCHES_EXACTLY + }) + + operation = Operation.OR +} +``` + +You can also pass multiple search criteria to the same filter. In this case, they are considered using `OR` by default. (Using `AND` on multiple search criteria is usually not useful.) The following example returns patients with a given name of exactly "Jay" or "Kat". + +```kotlin +fhirEngine.search { + filter(Patient.GIVEN, { + value = "Jay" + modifier = StringFilterModifier.MATCHES_EXACTLY + } , { + value = "Kat" + modifier = StringFilterModifier.MATCHES_EXACTLY + }) +} +``` + +### Reverse chaining + +The `has` function allows you to search for a resource based on other resources that reference it and functions similarly to [FHIR Search reverse chaining](https://build.fhir.org/search.html#has). In the following example, the search will return a list of Patients that: + +1. have a RelatedPerson that references that Patient in the `RelatedPerson.PATIENT` field +2. the RelatedPerson has a name matching "Ariel" + +In this case, the results will include a patient resource matching `patient1`, plus any others that were already created in the FhirEngine. + +```kotlin +val patient1 = Patient().apply{ + id = "1234567" + addName( + HumanName().apply { + addGiven("Alex") + family = "Lee" + } + ) +} + +val related1 = RelatedPerson().apply { + patient.reference = "${patient1.fhirType()}/${patient1.logicalId}" + addName( + HumanName().apply { + addGiven("Ariel") + family = "Lee" + } + ) +} + +fhirEngine.create(patient1) +fhirEngine.create(related1) + +val revinclude = fhirEngine.search { + has(RelatedPerson.PATIENT) { + filter (RelatedPerson.NAME, { + value = "Ariel" + }) + } +} +``` + +You can use `has` in combination with the other Search DSL features to create [complex searches](#complex-search-queries). + +### Search result modification + +You can specify several fields to control search results, similar to [FHIR Search results](https://build.fhir.org/search.html#modifyingresults). + +* `sort` - specify a Date, Number, or String field to sort the results by +* `count` - limit the results to a certain size +* `from` - start the results from a specified index + +```kotlin +val patients = fhirEngine.search { + filter (Patient.NAME, { + modifier = StringFilterModifier.CONTAINS + value = "Quinn" + }) + sort(Patient.FAMILY, Order.ASCENDING) + count = 100 + from = 0 +} +``` + +### Search filter parameters by type + +#### Number + +https://www.hl7.org/fhir/search.html#number + +Fields + +* `prefix` - A [FHIR search prefix](https://build.fhir.org/search.html#prefix), represented by [`ParamPrefixEnum`](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/ParamPrefixEnum.html). +* `value` - A `BigDecimal` of the value to search for. + +Search for all the Risk Assessments with probability greater than 0.8. + +```kotlin +fhirEngine.search { + filter(RiskAssessment.PROBABILITY, { + value = BigDecimal(0.8) + prefix = ParamPrefixEnum.GREATERTHAN + }) +} +``` + +#### Date + +https://www.hl7.org/fhir/search.html#date + +* `prefix` - A [FHIR search prefix](https://build.fhir.org/search.html#prefix), represented by [`ParamPrefixEnum`](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/ParamPrefixEnum.html). +* `value` - A `DateFilterValues` of the value to search for. Pass a [`DateType`](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-structures-r5/org/hl7/fhir/r5/model/DateType.html) or [`DateTimeType`](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-structures-r5/org/hl7/fhir/r5/model/DateTimeType.html) to the `of` function to create. + +Search for any patients born after 2013-03-14. + +```kotlin +fhirEngine.search { + filter( + Patient.BIRTHDATE, + { + prefix = ParamPrefixEnum.STARTS_AFTER + value = of(DateType("2013-03-14")) + } + ) +} +``` + +#### String + +https://www.hl7.org/fhir/search.html#string + +* `value` - The `String` to search for. +* `modifier` - An option from [`StringFilterModifier`](https://google.github.io/android-fhir/engine/engine/com.google.android.fhir.search/-string-filter-modifier/index.html), corresponding to a [FHIR string search](https://www.hl7.org/fhir/search.html#string) modifier. Default: `StringFilterModifier.STARTS_WITH` + +Search for any patients with a name with a given part containing "eve" at any position. This would include patients with the given name "Eve", "Evelyn", and also "Severine". + +```kotlin +val patients = fhirEngine.search { + filter (Patient.NAME, { + value = "eve" + modifier = StringFilterModifier.CONTAINS + }) +} +``` + +#### Token + +https://www.hl7.org/fhir/search.html#token + +* `value` - A `TokenFilterValue` of the value to search for. Pass the appropriate object type to the `of` function to create: `Boolean`, `String`, `UriType`, `CodeType`, `Coding`, `CodeableConcept`, `Identifier` + +Search for any patient with a gender that has the code "male". + +```kotlin +fhirEngine.search { + filter(Patient.GENDER, { + value = of(CodeType("male")) + }) +} +``` + +Search for any patients that are active. + +```kotlin +fhirEngine.search { + filter(Patient.ACTIVE, { + value = of(true) + }) +} +``` + +Search for any condition with a code "123" in the code system "http://example.org/codes". + +```kotlin +fhirEngine.search { + filter(Condition.CODE, { + value = of(CodeableConcept(Coding("http://example.org/codes", "123", ""))) + }) +} +``` + +#### Reference + +https://www.hl7.org/fhir/search.html#reference + +* `value` - a `String` of a resource reference. + +Search for all the observations where the subject references "Patient/123". + +```kotlin +fhirEngine.search { + filter(Observation.SUBJECT, { + value = "Patient/123" + }) +} +``` + +#### Quantity + +https://www.hl7.org/fhir/search.html#quantity + +* `prefix` - A [FHIR search prefix](https://build.fhir.org/search.html#prefix), represented by [`ParamPrefixEnum`](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/rest/param/ParamPrefixEnum.html). +* `value` - A `BigDecimal` of the value to search for. +* `system` - A `String` of the URI identifying the coding system. +* `unit` - A `String` of the coded form of the unit. + +Search for all the observations where the value of is about 5.4 mg, where mg is understood as a UCUM unit. + +```kotlin +fhirEngine.search { + filter(Observation.VALUE_QUANTITY, { + prefix = ParamPrefixEnum.APPROXIMATE + value = BigDecimal(5.4) + system = "http://unitsofmeasure.org" + unit = "mg" + }) +} +``` + +#### URI + +https://www.hl7.org/fhir/search.html#uri + +* `value` - a `String` of the URI to search for. + +Search for all the value sets with the exact URL "http://example.org/fhir/ValueSet/123". + +```kotlin +fhirEngine.search { + filter(ValueSet.URL, { + value = "http://example.org/fhir/ValueSet/123" + }) +} +``` + +### Search query examples + +#### Complex search queries + +Search for Patients in India who have completed their Influenza vaccination. + +```kotlin +fhirEngine.search { + has(Immunization.PATIENT) { + filter( + Immunization.VACCINE_CODE, { + value = of(Coding("http://hl7.org/fhir/sid/cvx", "140", "Influenza, seasonal, injectable, preservative free")) + } + ) + + // Follow Immunization.ImmunizationStatus + filter(Immunization.STATUS, { + value = of(Coding("http://hl7.org/fhir/event-status", "completed", "")) + } + ) + } + + filter( + Patient.ADDRESS_COUNTRY, { + modifier = StringFilterModifier.MATCHES_EXACTLY + value = "IN" + } + ) + } +``` + +#### Search Patient compartment for Encounters and Observations + +Search for all Encounters and Observations where the subject is patient ID "123". + +```kotlin +val observations = + fhirEngine.search { + filter(Observation.SUBJECT, { value = "Patient/123" }) + } + +val conditions = + fhirEngine.search { + filter(Condition.SUBJECT, { value = "Patient/123" }) +} +``` + +#### Search Patients with Observation by Code + +Search for all Patients where they are the subject of an Observation with the code "http://snomed.info/sct|386661006" or "http://loinc.org|45701-0" (different codes for fever). + +```kotlin +val patients = fhirEngine.search { + has(Observation.SUBJECT) { + filter( + Observation.CODE, + { + of(Coding("http://snomed.info/sct", "386661006", "Fever" )) + }, { + of(Coding("http://loinc.org", "45701-0", "Fever")) + } + ) + } +} +``` + +## Search using FHIR search queries + +You can also search resources in a FHIR Engine instance using [FHIR search queries](https://www.hl7.org/fhir/search.html). + +Complex queries including FHIRPath expressions, global common search parameters, modifiers, prefixes, chained parameters are not supported. + +```kotlin +val result = fhirEngine.search("Patient?active=true&gender=male&_sort=-name,gender&_count=11") +``` + +## Adding custom search parameters + +You can define custom search parameters, in addition to the ones defined in the [FHIR spec](https://www.hl7.org/fhir/searchparameter-registry.html), add them to FHIR Engine and use them to search for resources. Adding custom search parameters is particularly useful when you want to search for extensions defined in custom profiles. + +### Setting up custom search parameters + +```kotlin +class FhirApplicationTest : Application(){ + + override fun onCreate() { + super.onCreate() + + FhirEngineProvider.init( + FhirEngineConfiguration( + enableEncryptionIfSupported = true, + RECREATE_AT_OPEN, + ServerConfiguration("https://hapi.fhir.org/baseR4/"), + customSearchParameters = listOf( + SearchParameter().apply { + url = "http://example.com/SearchParameter/patient-mothersMaidenName" + addBase("Patient") + name = "mothers-maiden-name" + code = "mothers-maiden-name" + type = Enumerations.SearchParamType.STRING + expression = + "Patient.extension('http://hl7.org/fhir/StructureDefinition/patient-mothersMaidenName').value.as(String)" + description = "search on mother's maiden name" + }, +// Additional String Type Search param for Patient.identifier for value matching along with the standard Token Type provided by FHIR. + SearchParameter().apply { + url = "http://example.com/SearchParameter/patient-identifierPartial" + addBase("Patient") + name = "identifierPartial" + code = "identifierPartial" + type = Enumerations.SearchParamType.STRING + expression = "Patient.identifier.value" + description = "Search the identifier" + } + ) + ) + ) + } +} +``` + +### Searching with the added custom search parameters + +```kotlin +// Identifier partial search returns all Patients whose Patient.identifier.value starts with 5005- . +fhirEngine.search { + filter( + StringClientParam("identifierPartial"), + { + value = "5005-" + modifier = StringFilterModifier.STARTS_WITH + } + ) +} +``` + +```kotlin +// searching with the extension returns all Patients who have Marca as their Maiden name. +// (custom extension http://example.com/SearchParameter/patient-mothersMaidenName). +fhirEngine.search { + filter( + StringClientParam("mothers-maiden-name"), + { + value = "Marca" + modifier = StringFilterModifier.MATCHES_EXACTLY + } + ) +} +``` + +**NOTE:** +The engine doesn't automatically reindex existing resources after a new SearchParameter is added. Resources created after the new SearchParameter is created will be indexed accordingly. Updates to the existing resources will result in the reindexing of the resource. diff --git a/docs/use/FEL/Sync-data-with-FHIR-server.md b/docs/use/FEL/Sync-data-with-FHIR-server.md new file mode 100644 index 0000000000..0eaa80ce5b --- /dev/null +++ b/docs/use/FEL/Sync-data-with-FHIR-server.md @@ -0,0 +1,172 @@ +# Sync Data with FHIR Server + +This guide explains how to synchronize data between your Android app and a FHIR server using the Android FHIR Engine. The FHIR Engine provides two ways to achieve this: **one-time sync** and **periodic sync**. + +**One-time sync** allows you to trigger a synchronization job manually, on demand. This is useful for scenarios where you want to control when data is synchronized, such as when a user explicitly requests it. + +**Periodic sync** allows you to schedule a job that automatically synchronizes data with the FHIR server at regular intervals. This is useful for keeping the local data in your app up-to-date with the server. + +## Initial setup + +Before you can start syncing data, you need to perform some initial setup. + +### Server requirements + +The FHIR server you are syncing with must support the [optional capability to allow clients to `PUT` resources to locations that don't yet exist (upsert)](https://www.hl7.org/fhir/http.html#upsert). + +### Add dependencies and permissions + +* Add the `work-runtime-ktx` dependency to your app-level `build.gradle` file, typically `app/build.gradle`: + +```kotlin +dependencies { + // ... + implementation("androidx.work:work-runtime-ktx:2.8.1") +} +``` + +* Include the Internet permission in your `AndroidManifest.xml`: + +```xml + + + + + ... + + + +``` + +### Configure FhirEngine + +* During `FhirEngineProvider.init()`, provide a `ServerConfiguration` object with at least the `baseUrl` set to the URL of your FHIR server as part of the [`FhirEngineConfiguration`](https://github.com/google/android-fhir/blob/master/engine/src/main/java/com/google/android/fhir/FhirEngineProvider.kt#L106): + +```kotlin +FhirEngineProvider.init( + FhirEngineConfiguration( + enableEncryptionIfSupported = true, + databaseErrorStrategy = DatabaseErrorStrategy.RECREATE_AT_OPEN, + serverConfiguration = ServerConfiguration("https://your-fhir-server-url"), + ) +) +``` + +#### Advanced configuration + +The [`ServerConfiguration`](https://github.com/google/android-fhir/blob/master/engine/src/main/java/com/google/android/fhir/FhirEngineProvider.kt#L143) takes in other parameters as well. + +Optionally, you can customize network connection parameters like timeouts and gzip compression using [`NetworkConfiguration`](https://github.com/google/android-fhir/blob/master/engine/src/main/java/com/google/android/fhir/FhirEngineProvider.kt#L164). By default, `uploadWithGzip` is set to `false`. If you are uploading to Google Cloud FHIR Store or a HAPI FHIR Server, we recommend setting it to `true` as those two servers support gzip compression. + +If your server requires authentication, implement the [`HttpAuthenticator`](https://github.com/google/android-fhir/blob/master/engine/src/main/java/com/google/android/fhir/sync/HttpAuthenticator.kt#L33) interface and provide it to `ServerConfiguration`. This allows you to specify how the FHIR Engine should authenticate with the server. For example, let's say your server requires OAuth 2.0 Bearer Token authentication. To use it, implement the `HttpAuthenticator` interface using the [HttpAuthenticationMethod.Bearer](https://github.com/google/android-fhir/blob/master/engine/src/main/java/com/google/android/fhir/sync/HttpAuthenticator.kt#L52) function, which should return the bearer token string required by the server. It will be added to the header of all requests. + +For debugging purposes, you can configure the `httpLogger` parameter in `ServerConfiguration` to log the communication between the FHIR Engine and the server. + +Putting all this together, we can have a ServerConfiguration that looks like this: + +```kotlin + ServerConfiguration( + "https://hapi.fhir.org/baseR4/", + httpLogger = + HttpLogger( + HttpLogger.Configuration( + if (BuildConfig.DEBUG) HttpLogger.Level.BODY else HttpLogger.Level.BASIC + ) + ) { Timber.tag("App-HttpLog").d(it) }, + networkConfiguration = NetworkConfiguration(uploadWithGzip = true), + authenticator = { HttpAuthenticationMethod.Bearer("mySecureToken") } + ) +``` + +### Implement DownloadWorkManager + +Create a subclass of [`DownloadWorkManager`](https://github.com/google/android-fhir/blob/master/engine/src/main/java/com/google/android/fhir/sync/DownloadWorkManager.kt) to define how the engine should generate download requests and process responses from the server. You can refer to the [`TimestampBasedDownloadWorkManagerImpl`](https://github.com/google/android-fhir/blob/master/demo/src/main/java/com/google/android/fhir/demo/data/TimestampBasedDownloadWorkManagerImpl.kt) in the demo app for an example implementation. + +### Implement FhirSyncWorker + +Finally, provide an implementation of `FhirSyncWorker`. This class is responsible for defining how your app interacts with the FHIR Engine during synchronization. It has four functions to implement: + +* **`getDownloadWorkManager()`**: This should return the implementation of `DownloadWorkManager` you created earlier. +* **`getConflictResolver()`**: This controls how conflicts between the local and remote versions of resources are resolved. You can set it to `AcceptLocalConflictResolver` if the local version should take precedence, or `AcceptRemoteConflictResolver` if the remote version should. +* **`getFhirEngine()`**: This should return your application's `FhirEngine` instance. +* **`getUploadStrategy()`**: This defines how local changes are uploaded to the FHIR server. Currently, the only supported strategy is `UploadStrategy.AllChangesSquashedBundlePut`, which squashes all local changes into a single bundle and uses the `PUT` method to upload it. + +Here's an example implementation: + +```kotlin +class FhirPeriodicSyncWorker(appContext: Context, workerParams: WorkerParameters) : + FhirSyncWorker(appContext, workerParams) { + + override fun getDownloadWorkManager(): DownloadWorkManager { + return DownloadWorkManagerImpl() // Replace with your implementation + } + + override fun getConflictResolver() = AcceptLocalConflictResolver + + override fun getFhirEngine() = FhirApplication.fhirEngine(applicationContext) + + override fun getUploadStrategy(): UploadStrategy { + return UploadStrategy.AllChangesSquashedBundlePut + } +} +``` + +Remember to replace `DownloadWorkManagerImpl` with your actual implementation. + +See the [`DemoFhirSyncWorker`](https://github.com/google/android-fhir/blob/master/demo/src/main/java/com/google/android/fhir/demo/data/DemoFhirSyncWorker.kt) in the demo app for a more complete example. + +## Perform synchronization + +Once you have completed the initial setup, you can start syncing data with the FHIR server. + +### One-Time Sync + +Use the [Sync.oneTimeSync](https://github.com/google/android-fhir/blob/master/engine/src/main/java/com/google/android/fhir/sync/Sync.kt#L54) API: + +```kotlin +Sync.oneTimeSync(applicationContext) +``` + +This triggers a single sync job. You can collect the `SyncJobStatus` from the returned `Flow` to monitor the progress and result of the job. + +```kotlin +CoroutineScope.launch { + Sync.oneTimeSync(applicationContext) + .shareIn(this, SharingStarted.Eagerly, 0) + .collect { /* Handle SyncJobStatus here */ } +} +``` + +### Periodic Sync + +Use the [Sync.periodicSync](https://github.com/google/android-fhir/blob/master/engine/src/main/java/com/google/android/fhir/sync/Sync.kt#L80) API. + +```kotlin +Sync.periodicSync( + applicationContext, + PeriodicSyncConfiguration( + syncConstraints = Constraints.Builder().build(), + repeat = RepeatInterval(interval = 15, timeUnit = TimeUnit.MINUTES) + ) +) +``` + +This schedules a periodic sync job that runs according to the specified `PeriodicSyncConfiguration`. You can customize the sync constraints and repeat interval as needed. Similar to one-time sync, you can collect the `PeriodicSyncJobStatus` from the returned `Flow` to monitor the job. + +```kotlin +CoroutineScope.launch { + Sync.periodicSync( + application.applicationContext, + periodicSyncConfiguration = + PeriodicSyncConfiguration( + syncConstraints = Constraints.Builder().build(), + repeat = RepeatInterval(interval = 15, timeUnit = TimeUnit.MINUTES) + ) + ) + .shareIn(this, SharingStarted.Eagerly, 10) + .collect { /**Handle SyncJobStatus Here*/ } +} +``` + +Note: Both sync methods utilize the WorkManager library under the hood. For more information on WorkManager, refer to the [official documentation](https://developer.android.com/reference/androidx/work/WorkManager) diff --git a/docs/use/FEL/fhir-engine-components.png b/docs/use/FEL/fhir-engine-components.png new file mode 100644 index 0000000000000000000000000000000000000000..493c6cc9d2b0615413c15dbc7305fc0bcb3e19af GIT binary patch literal 32754 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 +[[fhir-engine-components.png|width=640px]] +

+ +

+Figure 1: FHIR Engine Library components +

+ +## FHIR Engine Library components + +The FHIR Engine library comprises an SQLLite database for offline storage of FHIR Resources and a suite of APIs (sync, search, data-access) for managing FHIR resources on the device. + +### Local db for offline storage of FHIR resources + +* The backbone of the FHIR Engine Library is the **SQLite database** storing FHIR resources in serialized JSON format +* Data stored in the on device storage is **[stored securely](Privacy-Security.md)** +* The database has **indexes for enabling fast retrieval** of resources based on [FHIR Search](https://www.hl7.org/fhir/search.html) + +### FHIR Engine APIs + +* **Data Access API**: basic access to local FHIR resources, namely, the CRUD operations: create, read, update, and delete. This relies on the HAPI FHIR Structures libraries ([api docs](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-structures-r4/) | [documentation](https://hapifhir.io/hapi-fhir/docs/model/working_with_resources.html)) +* **Search API**: a Kotlin DSL (domain-specific language) for searching local FHIR resources +* **Sync API**: synchronizes local FHIR resources with a remote FHIR server/store (such as [HAPI FHIR](https://hapifhir.io/hapi-fhir//) or [Google Cloud Healthcare API](https://cloud.google.com/healthcare-api/docs/how-tos/fhir)) diff --git a/docs/use/SDCL/Author-questionnaires.md b/docs/use/SDCL/Author-questionnaires.md new file mode 100644 index 0000000000..985e51c79a --- /dev/null +++ b/docs/use/SDCL/Author-questionnaires.md @@ -0,0 +1,625 @@ +# Author Questionnaires + +An Android app developer can use the Structured Data Capture Library's capabilities without a deep understanding of FHIR or FHIR questionnaires; similarly, healthcare data experts can build questionnaires independently from the app development workflow. However, understanding FHIR Questionnaires can be helpful for developers to debug issues, implement more advanced features, or authoring questionnaires themselves. This section is meant to provide Android developers a brief overview of the Questionnaire with a focus on the parts relevant for the Structured Data Capture Library. + +You should be familiar with: + +* Reading and writing [JSON](https://www.json.org/) +* Working with data structures besides FHIR +* (Recommended) [FHIR overview for developers](https://www.hl7.org/fhir/overview-dev.html) + +The Structured Data Capture Library uses the [FHIR Questionnaire](https://www.hl7.org/fhir/questionnaire.html) as its fundamental data structure. A FHIR Questionnaire is a structured set of questions for collecting data from the end users. In addition, the [Structured Data Capture](http://hl7.org/fhir/uv/sdc/) (SDC) implementation guide supplements questionnaires by defining capabilities for more advanced control of rendering and question flow. + +* [Example questionnaires from HL7](https://www.hl7.org/fhir/questionnaire-examples.html) +* [Example questionnaires from the SDC IG](http://hl7.org/fhir/uv/sdc/artifacts.html#example-example-instances) + +## Questionnaire builders + +There are a number of web-based tools for building FHIR Questionnaires like the [NLM Form Builder](https://lhcformbuilder.nlm.nih.gov/), which are a great starting point for both developers and non-developers to create and edit Questionnaires. They allow you to add and edit questions using a simple drag-and-drop interface, and include some advanced features like conditional display. Many features which require extensions like [data extraction and population](#data-extraction-and-population) or [item control](FHIR-specification-support.md#item-control) are not included in the UI but can be manually added by saving as a JSON file and editing the file. Typically, if you load a file with manually added extensions back into a Questionnaire builder and edit an item with an extension, the extension is maintained. However, if you add new items any desired extensions would need to be manually added. + +One possible workflow is to have a non-developer create an initial version of a questionnaire using a Questionnaire builder tool, then saving it as a JSON file and it handing off to someone familiar with the FHIR Questionnaire syntax to add any desired extensions or other advanced functionality manually. + +Questionnaire builders may support different parts of the SDC implementation guide than the Structured Data Capture Library does, so double-check the SDC Library's [FHIR specification support](FHIR-specification-support.md) if something doesn't seem to be working. + +## Questionnaire basics + +Following is an example of a very simple Questionnaire: + +```json +{ + "resourceType": "Questionnaire", + "status": "draft", + "item": [ + { + "linkId": "1", + "text": "Name", + "type": "string" + } + ] +} + +``` + +The `item` array contains a single question object which collects a string. The optional `text` field means this question will have a text label containing "Name" when rendered. `linkId` is used to identify the specific component of the Questionnaire. Two common conventions for `linkId` are using the numeric representation of the nested structure (`1`, `1.1`, `1.2`, etc.), or descriptive names (`patient-info`, `patient-info-name`, `patient-info-dob`, for example). + +Let's look at a more complex Questionnaire, focused on the top-level `item` element: + +```json +"item": [ + { + "linkId": "1", + "text": "Patient Information", + "type": "group", + "item": [ + { + "linkId": "1.1", + "text": "Name", + "type": "string", + "required": true + }, + { + "linkId": "1.2", + "text": "Date of birth", + "type": "date" + } + ] + }, + { + "linkId": "2", + "text": "Demographic Information", + "type": "group", + "item": [ + { + "linkId": "2.1", + "text": "Cats are better than dogs", + "type": "boolean" + }, + { + "linkId": "2.2", + "text": "Correct!", + "type": "display", + "enableWhen": [ + { + "question": "2.1", + "operator": "=", + "answerBoolean": true + } + ] + } + ] + } +] +``` + +There are [several options](https://www.hl7.org/fhir/valueset-item-type.html) for the `type` member of `item` objects. The Structured Data Capture Library selects the UI component to use when rendering based on the type. This example also uses the `group` type where `text` acts as section headers and child item objects are logically grouped. + +Some Questionnaire elements control validation or rendering logic. For example, item `1.1` is required, and item `2.1.1` is only shown if item `2.1` is `true`. + +The next example of an item object uses extensions from the SDC implementation guide and also demonstrates the `choice` type: + +```json +... +{ + "linkId": "1.3", + "text": "Gender", + "type": "choice", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl", + "valueCodeableConcept": { + "coding": [ + { + "system": "http://hl7.org/fhir/questionnaire-item-control", + "code": "radio-button", + "display": "Radio Button" + } + ] + } + }, + { + "url" : "http://hl7.org/fhir/StructureDefinition/questionnaire-choiceOrientation", + "valueCode" : "horizontal" + } + ], + "answerOption": [ + { + "valueCoding": { + "code": "female", + "display": "Female", + "system": "http://hl7.org/fhir/gender-identity" + } + }, + { + "valueCoding": { + "code": "male", + "display": "Male", + "system": "http://hl7.org/fhir/gender-identity" + } + }, + { + "valueCoding": { + "code": "other", + "display": "Other", + "system": "http://hl7.org/fhir/gender-identity" + } + } + ] +}, +... +``` + +There are two extensions: the `questionnaire-itemControl` specifies that the `choice` type question should use radio buttons (and not a dropdown menu or checkboxes, for example), and the `questionnaire-choiceOrientation` says question options should be rendered horizontally. + +### Popular features and extensions + +#### Pagination + +[Page](https://build.fhir.org/codesystem-questionnaire-item-control.html#questionnaire-item-control-page) item control on group items for paginated questionnaires. Note: the `page` control type is not yet part of a stable FHIR release, but has been added to the SDC Library due to developer demand. + +Example: + +```json +"item": [ + { + "type": "group", + "linkId": "pagedemo", + "text": "Page title", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl", + "valueCodeableConcept": { + "coding": [ + { + "system": "http://hl7.org/fhir/questionnaire-item-control", + "code": "page", + "display": "Page" + } + ], + "text": "Page" + } + } + ], + "item": [ ... ] + } +] +``` + +#### Value constraints + +[Value constraints](http://hl7.org/fhir/uv/sdc/behavior.html#value-constraints) to add validation to responses. Currently supported: `maxLength`, `minLength`, `regex`, `minValue`, `maxValue`. + +Example: + +```json +"item": [ + { + "type": "decimal", + "linkId": "weightdemo", + "text": "Weight, Measured", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/minValue", + "valueDecimal": 1 + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/maxValue", + "valueDecimal": 100 + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/maxDecimalPlaces", + "valueInteger": 2 + } + ] + } +] +``` + +#### Conditional display + +Conditional display using [enableWhen](http://hl7.org/fhir/uv/sdc/behavior.html#enableWhen) and [enableWhenExpression](http://hl7.org/fhir/uv/sdc/expressions.html#enableWhenExpression). + +Example: + +```json +"item": [ + { + "linkId": "sex", + "text": "Sex", + "type": "choice", + "answerOption": [ + { + "valueCoding": { + "code": "male", + "display": "Male" + } + }, + { + "valueCoding": { + "code": "female", + "display": "Female" + } + } + ] + }, + { + "linkId": "birthdate", + "text": "Birth date" + "type": "date", + }, + { + "linkId" : "example1", + "text": "Shown only if female", + "type": "text", + "enableWhen": [ + { + "question" : "sex", + "operator": "=", + "answerCoding": { + "code": "female" + } + } + ] + }, + { + "linkId" : "example2", + "text": "Shown only if female over 40 years old", + "type": "text", + "extension": [ + { + "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-enableWhenExpression", + "valueExpression": { + "description": "female over 40", + "language": "text/fhirpath", + "expression": "%resource.repeat(item).where(linkId='sex').answer.value.code ='female' and today().toString().substring(0, 4).toInteger() - %resource.repeat(item).where(linkId='birthdate').answer.value.toString().substring(0, 4).toInteger() >= 40" + } + } + ], + } +] +``` + +#### Autocomplete + +[Autocomplete](http://hl7.org/fhir/R4/codesystem-questionnaire-item-control.html#questionnaire-item-control-autocomplete) for choice-type questionnaire item. + +Example: + +```json +"item": [ + { + "linkId": "state" + "text": "US State", + "type": "choice", + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/questionnaire-itemControl", + "valueCodeableConcept": { + "coding": [ + { + "system": "http://hl7.org/fhir/questionnaire-item-control", + "code": "autocomplete", + "display": "autocomplete" + } + ] + } + } + ], + "answerOption": [ + { + "valueCoding": { + "code": "AL", + "display": "Alabama" + } + }, + { + "valueCoding": { + "code": "AK", + "display": "Alaska" + } + }, + { + "valueCoding": { + "code": "AS", + "display": "American Samoa" + } + }, + { + "valueCoding": { + "code": "AZ", + "display": "Arizona" + } + }, + { + "valueCoding": { + "code": "AR", + "display": "Arkansas" + } + }, + ... + ] + } +] +``` + +## Data extraction and population + +Mapping FHIR QuestionnaireResponses to other FHIR resources (and back) allows the structured data capture process to be more tightly integrated with clinical workflows. + +For example, if your application has a questionnaire for new patient registration, your ultimate goal may be to create a [FHIR Patient resource](https://www.hl7.org/fhir/patient.html) based on the answers provided to use in your application. Or, if your application has a questionnaire for entering test results, you could create a FHIR Observation resource. The process of mapping a FHIR QuestionnaireResponse to one or more other FHIR resources is called [extraction](http://hl7.org/fhir/uv/sdc/extraction.html). + +On the other hand, you may want to reduce data entry by loading values from existing FHIR resources into your questionnaire. For example, if a questionnaire asks for a patient's name and age, you can pre-populate that information from an existing FHIR Patient resource. The process of mapping one or more FHIR resources to a FHIR QuestionnaireResponse is called [population](http://hl7.org/fhir/uv/sdc/populate.html). + +### Definition-based extraction + +A questionnaire using [definition-based extraction](http://hl7.org/fhir/uv/sdc/extraction.html#definition-based-extraction) includes the [questionnaire-itemExtractionContext](http://hl7.org/fhir/uv/sdc/StructureDefinition-sdc-questionnaire-itemExtractionContext.html) extension to identify the FHIR resource to extract, and fill in the `Questionnaire.item.definition` to specify the resource or profile element that Questionnaire item corresponds to: + +```json +{ + "resourceType": "Questionnaire", + "status": "draft", + "extension": [ + { + "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemExtractionContext", + "valueExpression": { + "language": "application/x-fhir-query", + "expression": "Patient", + "name": "patient" + } + } + ], + "item": [ + { + "linkId": "PR", + "type": "group", + "item": [ + { + "linkId": "PR-name", + "type": "group", + "definition": "http://hl7.org/fhir/StructureDefinition/Patient#Patient.name", + "item": [ + { + "linkId": "PR-name-given", + "definition": "http://hl7.org/fhir/StructureDefinition/Patient#Patient.name.given", + "type": "string", + "text": "First Name" + }, + { + "linkId": "PR-name-family", + "definition": "http://hl7.org/fhir/StructureDefinition/Patient#Patient.name.family", + "type": "string", + "text": "Family Name" + } + ] + }, + { + "linkId": "PR-birthdate", + "definition": "http://hl7.org/fhir/StructureDefinition/Patient#Patient.birthDate", + "type": "date", + "text": "Date of Birth" + }, + { + "linkId": "PR-id", + "type": "group", + "definition": "http://hl7.org/fhir/StructureDefinition/Patient#Patient.identifier", + "item": [ + { + "extension" : [ + { + "url" : "http://hl7.org/fhir/StructureDefinition/questionnaire-hidden", + "valueBoolean" : true + }, + { + "url" : "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression", + "valueString" : "http://example.org/mrn" + } + ], + "linkId": "PR-name-id-url", + "definition": "http://hl7.org/fhir/StructureDefinition/Patient#Patient.identifier.system", + "type": "string" + }, + { + "linkId": "PR-name-id", + "definition": "http://hl7.org/fhir/StructureDefinition/Patient#Patient.identifier.value", + "type": "string", + "text": "Patient Id" + } + ] + } + ] + } + ] +} +``` + +This example extracts to a Patient resource. In order to extract to a Patient.identifier, it includes the hidden `PR-name-id-url` item to populate the `Patient.identifier.system` element programmatically. + +One major limitation of expression-based extraction is that the questionnaire must be structured the same as the resource you're extracting to. For example, there is no simple way to extract answers from a single group to multiple different FHIR resources. + +See the [SDC implementation guide on definition-based extraction](http://hl7.org/fhir/uv/sdc/extraction.html#definition-based-extraction) for more information. + +### StructureMap-based extraction + +A questionnaire using [StructureMap-based extraction](http://hl7.org/fhir/uv/sdc/extraction.html#structuremap-based-extraction) includes the `sdc-questionnaire-targetStructureMap` extension specifying the structure map to use when transforming the QuestionnaireResponse to other FHIR resources. + +```json +{ + "resourceType": "Questionnaire", + "status": "active", + "extension": [ + { + "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-targetStructureMap", + "valueCanonical": "http://example.org/fhir/StructureMap/PatientRegistration" + } + ], + "item": [ + { + "linkId": "PR", + "type": "group", + "item": [ + { + "linkId": "PR-name", + "type": "group", + "item": [ + { + "linkId": "PR-name-given", + "type": "string", + "text": "First Name" + }, + { + "linkId": "PR-name-family", + "type": "string", + "text": "Family Name" + } + ] + }, + { + "linkId": "PR-birthdate", + "type": "date", + "text": "Date of Birth" + }, + { + "linkId": "PR-name-id", + "type": "string", + "text": "Patient Id" + } + ] + } + ] +} +``` + +Structure maps are typically authored in the [FHIR mapping language](http://hl7.org/fhir/R4/mapping-language.html), although they can also be represented by the [StructureMap resource](http://hl7.org/fhir/R4/structuremap.html): + +``` +map "http://example.org/fhir/StructureMap/PatientRegistration" = 'PatientRegistration' +uses "http://hl7.org/fhir/StructureDefinition/QuestionnaireReponse" as source +uses "http://hl7.org/fhir/StructureDefinition/Bundle" as target + +group PatientRegistration(source src : QuestionnaireResponse, target bundle: Bundle) { + src -> bundle.id = uuid() "rule_bundle_id"; + src -> bundle.type = 'collection' "rule_bundle_type"; + src -> bundle.entry as entry, entry.resource = create('Patient') as patient then + ExtractPatient(src, patient) "rule_extract_patient"; +} + +group ExtractPatient(source src : QuestionnaireResponse, target tgt : Patient) { + src.item as item where(linkId = 'PR') then { + item.item as inner_item where (linkId = 'patient-0-birth-date') then { + inner_item.answer first as ans then { + ans.value as val -> tgt.birthDate = val "rule_birthdate"; + }; + }; + + item.item as inner_item where (linkId = 'PR-name-id') then { + inner_item.answer first as ans -> tgt.identifier = create('Identifier') as id then { + ans.value -> id.system = 'http://example.org/mrn' "rule_name_id_code"; + ans.value as val -> id.value = val "rule_name_id_val"; + }; + }; + + item.item as nameItem where(linkId = 'PR-name') -> tgt.name = create('HumanName') as patientName then { + nameItem.item as famItem where (linkId = 'PR-name-family') then { + famItem.answer first as family then { + family.value as val -> patientName.family = val "rule_name_family"; + }; + }; + src -> patientName.given = evaluate(nameItem, ${"$"}this.item.where(linkId = 'PR-name-given').answer.value) "rule_name_given"; + }; + }; +} +``` + +The `PatientRegistration` group creates a Bundle to contain the other resources, which is required by the Structured Data Capture library, then creates an empty Patient and continues to `ExtractPatient`. Most of the example simply searches for items by `linkId` and then navigates the questionnaire's `item` data structure to set Patient element values. For the `Patient.name` element, the example uses the same strategy for the extraction rule `rule_name_family`, but also demonstrates using the [FHIRPath language](https://hl7.org/fhirpath/) to navigate and search the questionnaire structure with the extraction rule `rule_name_given`. + +Relies on HAPI FHIR implementation which does not support all features of mapping language, mostly convenience features so if it doesn't work try a more verbose form. + +See the [FHIR mapping language specification](http://hl7.org/fhir/R4/mapping-language.html) and [FHIR mapping language tutorial](http://hl7.org/fhir/R4/mapping-tutorial.html) for more information. + +The [online fhirpath.js demo](https://hl7.github.io/fhirpath.js/) is useful for learning and iterating on [FHIRPath](https://hl7.org/fhirpath/) expressions. + +### Expression-based population + +A questionnaire using [expression-based population](http://hl7.org/fhir/uv/sdc/populate.html#expression-based-population) primarily relies on the `sdc-questionnaire-initialExpression` extension to specify the starting value for each questionnaire item: + +```json +{ + "resourceType": "Questionnaire", + "status": "active", + "item": [ + { + "linkId": "PR", + "type": "group", + "item": [ + { + "extension" : [ + { + "url" : "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression", + "valueExpression" : { + "language" : "text/fhirpath", + "expression" : "Patient.name.first().select(given.first() + ' ' + family.first())" + } + } + ], + "linkId": "PR-name", + "type": "string", + "text": " Full name" + }, + { + "extension" : [ + { + "url" : "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression", + "valueExpression" : { + "language" : "text/fhirpath", + "expression" : "Patient.birthDate" + } + } + ], + "linkId": "PR-birthdate", + "type": "date", + "text": "Date of Birth" + }, + { + "extension" : [ + { + "url" : "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression", + "valueExpression" : { + "language" : "text/fhirpath", + "expression" : "Patient.identifier.where(system='http://example.org/mrn').value" + } + } + ], + "linkId": "PR-name-id", + "type": "string", + "text": "Patient Id" + } + ] + } + ] +} +``` + +Some external examples use FHIR search queries (where `language` is `"application/x-fhir-query"`) - these are not well supported by the Structured Data Capture library as you must directly pass all resources needed for population. + +You can test expression-based population for the example questionnaire with this Patient resource: + +```json +{ + "resourceType": "Patient", + "identifier": [ + { + "system": "http://example.org/mrn", + "value": "abcd-efgh-ijkl-mnop" + } + ], + "active": true, + "name": [ + { + "family": "Ali", + "given": [ + "Salman" + ] + } + ], + "birthDate": "1968-09-17" +} +``` diff --git a/docs/use/SDCL/Customize-how-a-Questionnaire-is-displayed.md b/docs/use/SDCL/Customize-how-a-Questionnaire-is-displayed.md new file mode 100644 index 0000000000..0541490405 --- /dev/null +++ b/docs/use/SDCL/Customize-how-a-Questionnaire-is-displayed.md @@ -0,0 +1,133 @@ +# Customize how a Questionnaire is displayed + +The Structured Data Capture Library provides default UI components and styles to +render FHIR Questionnaire resources based on +[Material Design](https://material.io/design) and the +[Structured Data Capture Implementation Guide](https://build.fhir.org/ig/HL7/sdc/). +In practice, you may want to customize how questionnaires look, and this guide +explains the two primary ways to do so: + +* Adjust the existing components to match the style of the rest of your + application +* Create new components to collect information in non-standard ways, e.g. + connected devices + +## Customize styles + +The Structured Data Capture Library includes a default +[theme](https://developer.android.com/guide/topics/ui/look-and-feel/themes) +[`Theme.Questionnaire`](https://github.com/google/android-fhir/blob/master/datacapture/src/main/res/values/styles.xml#L36) +which defines a number of custom attributes used to style questionnaires. For +example, `questionnaireQuestionTextStyle` defines the style for all question +text, and changing it affects all rendered questionnaires. The custom attributes +are: + +* `groupHeaderTextAppearanceQuestionnaire` +* `questionnaireQuestionTextStyle` +* `questionnaireSubtitleTextStyle` +* `questionnaireRadioButtonStyle` +* `questionnaireCheckBoxStyle` +* `questionnaireDropDownTextStyle` +* `questionnaireDropdownLayoutStyle` +* `questionnaireTextInputLayoutStyle` +* `questionnaireTextInputEditTextStyle` +* `questionnaireChipStyle` +* `questionnaireDialogTitleStyle` +* `questionnaireDialogButtonStyle` +* `questionnaireAddAnotherAnswerButtonStyle` +* `questionnaireErrorTextStyle` +* `questionnaireButtonStyle` +* `questionnaireSubmitButtonStyle` + +To customize the styles used to render questionnaires, create a theme with +different values for the custom attributes. A simple way to do this is to extend +the `Theme.Questionnaire` theme and override the attributes you want to change. + +For example, to change the appearance of question text, open your project's +`res/values/styles.xml` file and add a new theme that extends +`Theme.Questionnaire`, then set the `headerTextAppearanceQuestionnaire` +attribute to your preferred value: + +```xml + +``` + +Next, edit your application's default theme, typically in the +`res/values/themes.xml` file, and add the attribute `questionnaire_theme` set to +the new theme you just created: + +```xml + +``` + +## Custom questionnaire components + +The Structured Data Capture Library uses +[custom UI components](https://github.com/google/android-fhir/tree/master/datacapture/src/main/java/com/google/android/fhir/datacapture/views) +to render questions in a questionnaire. There are predefined components for most +question item types so you do not need to do anything special for most +questions. However, if you want to render a question in a way not described in +the FHIR standard of the SDC implementation guide, you can create a custom +component. + +### Create a custom component + +In order to create a custom component: + +1. Create a layout for the custom component + ([example](https://github.com/google/android-fhir/blob/master/catalog/src/main/res/layout/custom_number_picker_layout.xml)). +2. Create a class for your component that implements + `QuestionnaireItemViewHolderFactory` + ([example](https://github.com/google/android-fhir/blob/master/catalog/src/main/java/com/google/android/fhir/catalog/CustomNumberPickerFactory.kt)). + In that class: + 1. Pass the layout resource for your custom component in the constructor of + your custom factory. + 2. Override the `getQuestionnaireItemViewHolderDelegate()` function. It + must return a `QuestionnaireItemViewHolderDelegate` which implements the + following functions: +3. `init`: a delegate function for the `init` function of + `RecyclerView.ViewHolder` +4. `bind`: a delegate function for the `bind` function of + `RecyclerView.ViewHolder` +5. `displayValidationResult`: displays the validation result for the answer(s) + provided by the user +6. `setReadOnly`: configures the UI based on the read-only status of the + questionnaire item + +### Apply a custom component to questions + +Now that you have defined the custom widget and its behavior, it is time to +configure the Structured Data Capture Library in order for the custom widget to +be applied to the appropriate questions. + +1. Create a QuestionnaireFragment.QuestionnaireItemViewHolderFactoryMatcher + ([example](https://github.com/google/android-fhir/blob/master/catalog/src/main/java/com/google/android/fhir/catalog/CustomQuestionnaireFragment.kt#L26)) + that defines: + 1. factory: The custom component factory to use. + 2. matches: A predicate function which, given a + [`Questionnaire.QuestionnaireItemComponent`](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/Questionnaire.QuestionnaireItemComponent.html), + returns true if the factory should apply to that item. +2. Create a custom implementation of `QuestionnaireFragment` that + overrides `getCustomQuestionnaireItemViewHolderFactoryMatchers` + ([example](https://github.com/google/android-fhir/blob/master/catalog/src/main/java/com/google/android/fhir/catalog/CustomQuestionnaireFragment.kt#L22)). + It should return a list that contains your + `QuestionnaireItemViewHolderFactoryMatcher`. +3. When rendering your questionnaire, use your custom implementation of + QuestionnaireFragment instead. + +## Localize questionnaires + +When rendering your questionnaire, the library will look for the +[translation extension](http://hl7.org/fhir/extension-translation.html), and if +the lang element matches the application default locale, will use the value of +the content element of the extension instead of the text element of the +questionnaire item. You can also use the +[Locale.setDefault()](https://developer.android.com/reference/java/util/Locale#setDefault\(java.util.Locale\)) +method to manually set the locale to check against. diff --git a/docs/use/SDCL/Demo-app.md b/docs/use/SDCL/Demo-app.md new file mode 100644 index 0000000000..db3f56c23a --- /dev/null +++ b/docs/use/SDCL/Demo-app.md @@ -0,0 +1,11 @@ +# Demo App + +![Catalog App Hero Image](https://user-images.githubusercontent.com/7772901/171482222-7b3a4b55-3cb5-4deb-bf25-bc1e44fe9017.png) + +The *Structured Data Capture Catalog* demonstrates the capabilities of Structured Data Capture Library. In the Structured Data Capture Catalog you can see and interact with components and layouts that are supported by the Structured Data Capture library. The components and layouts are interactive, so you can see various states, interactions and transitions. + +To try out the Structured Data Capture Catalog app, you can either run the catalog module in Android Studio or run the following Gradle command: + +```shell +./gradlew :catalog:installDebug +``` diff --git a/docs/use/SDCL/FHIR-specification-support.md b/docs/use/SDCL/FHIR-specification-support.md new file mode 100644 index 0000000000..b446c73193 --- /dev/null +++ b/docs/use/SDCL/FHIR-specification-support.md @@ -0,0 +1,213 @@ +# FHIR specification support + +There are two specifications that serve as requirements for the library: + +* [FHIR Questionnaire](https://www.hl7.org/fhir/questionnaire.html) +* [Structured Data Capture Specification](http://hl7.org/fhir/uv/sdc/) + +In this section, we will provide details on how each requirement in these two specifications is supported by the library. + +## FHIR Questionnaire + +### Questionnaire item + +The following table summarizes the library's support for the key fields in the [questionnaire item element](https://www.hl7.org/fhir/questionnaire-definitions.html#Questionnaire.item). + +| | Support | Notes | +|:------------------|:-------:|:--------------------------------| +| linkId | ✅ | | +| definition | ✅ | See [Definition-based extraction](http://build.fhir.org/ig/HL7/sdc/extraction.html#definition-based-extraction) | +| code | ⛔️ | | +| prefix | ✅ | | +| text | ✅ | | +| type | ✅ | See [Questionnaire item type](#questionnaire-item-type) | +| enableWhen | ✅ | | +| enableBehavior | ✅ | | +| required | ✅ | | +| repeats | ✅ | | +| readOnly | ✅ | | +| maxLength | ✅ | For text only | +| answerConstraint | ⛔️ | | +| answerValueSet | ✅ | | +| answerOption | ✅ | | +| initial | ✅ | | +| item | ⚠️ | Items nested under group are supported (see [#726](https://github.com/google/android-fhir/issues/726)); items nested under non-group questions are not yet supported (see [#910](https://github.com/google/android-fhir/issues/910)). | + +### Questionnaire item type + +The following table summarizes the library's support for [questionnaire item types](https://www.hl7.org/fhir/codesystem-item-type.html). + +|Item type | Support | Example | Notes | +|:------------------|:-------:|:------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------| +| Group | ✅ | | | +| Display | ✅ | | | +| Question | ✅ | | See sub-types below | +| Boolean | ✅ | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_boolean_choice.json) | | +| Decimal | ✅ | | | +| Integer | ✅ | | | +| Date | ✅ | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_date_picker.json) | | +| Date time | ✅ | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_date_time_picker.json) | | +| Time | ⛔️ | | | +| String | ✅ | | Rendered as single-line text box | +| Text | ✅ | | Rendered as multi-line text box | +| Url | ⛔️ | | | +| Choice | ✅ | | | +| ~~Open Choice~~ | ✅ | | Deprecated in R5. Use `answerConstraint` instead. | +| Attachment | ✅ | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_attachment.json) | | +| Reference | ⛔️ | | | +| Quantity | ✅ | | | + +## Structured Data Capture Specification + +### Advanced form rendering + +This section summarizes the library's support for [advanced form rendering](http://build.fhir.org/ig/HL7/sdc/rendering.html). + +#### Text appearance + +| Code | Support | Example | Notes | +|:-------------------|:-------:|:--------|:-------------------------| +| rendering-style | ⛔️ | | | +| rendering-xhtml | ⛔️ | | | +| displayCatagory | ⚠️ | | `instructions` code only | +| openLabel | ⛔️ | | | +| hidden | ✅ | | | +| itemMedia | ✅ | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_item_media.json) | | +| itemAnswerMedia | ✅ | | | + +#### Control appearance + +| Control appearance | Support | Notes | +|:-------------------|:--------|:------------------| +| itemControl | ✅ | See below | +| choiceOrientation | ✅ | | +| sliderStepValue | ✅ | | +| width | ⛔️ | | +| collapsible | ⛔️ | | + +##### Item control + +The [`itemControl`](https://build.fhir.org/ig/HL7/fhir-extensions/ValueSet-questionnaire-item-control.html) extension allows for the selection of a specific control widget for questionnaire items. See [example usage](http://build.fhir.org/ig/HL7/sdc/examples.html#itemControl). Item controls are only compatible with certain questionnaire item types (e.g. drop down item control cannot be applied to boolean type questions). This is listed in the `Compatible item type` column in the following table. Unsupported item controls are omitted in the table below. + +| Item control | Compatible item type | Example | Notes | Image | +|:--------------|:---------------------|:--------|:----------------------------------------------|:-----:| +| Page | Group | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/layout_paginated.json) | | | +| Fly-over | Display | | | +| Help-Button | Display | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_help.json) | | | +| Auto-complete | Choice | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_auto_complete.json) | Filter-forward based on inlined answerOptions | | +| Drop down | Choice | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_dropdown.json) | Default for 4 or more answer options | [](sdc-ref-dropdown.png) | +| Check-box | Choice | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_multi_select_choice.json) | Default for repeat answers | | +| Radio Button | Choice | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_single_choice.json) | Default for less than 4 answer options | | +| Slider | Integer | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_slider.json) | | | + +#### Additional display content + +| Code | Support | Notes | +|:-------------------|:-------:|:----------------------------------------------------------------| +| supportLink | ⛔️ | | +| choiceColumn | ⛔️ | | +| optionPrefix | ⛔️ | | +| valueset-label | ⛔️ | | +| entryFormat | ⚠️ | Used in SDC for user guidance, not for validation. However, we use it to validate date where appropriate. See [#1850](https://github.com/google/android-fhir/issues/1850). | +| shortText | ⛔️ | | + +#### Other + +| Code | Support | Notes | +|:-------------------------|:-------:|:-----------------------------------| +| required | ✅ | | +| repeats | ✅ | | +| readOnly | ✅ | | +| rendering-styleSensitive | ⛔️ | | +| optionalDisplay | ⛔️ | | + +### Enhanced behavior + +This section summarizes the library's support for [form behavior and calculation](http://hl7.org/fhir/uv/sdc/behavior.html). + +#### Value constraints + +The library supports the following [value constraints](http://hl7.org/fhir/uv/sdc/behavior.html#value-constraints) which limit the allowed values for answers. + +| Value constraint | Support | Notes | +|:-------------------|:-------:|:--------------| +| maxLength | ✅ | For text only | +| minLength | ✅ | For text only | +| regex | ✅ | | +| minValue | ✅ | | +| maxValue | ✅ | | +| minQuantity | ⛔️ | | +| maxQuantity | ⛔️ | | +| maxDecimalPlaces | ✅ | | +| mimeType | ⛔️ | | +| maxSize | ⛔️ | | + +#### Choice restriction + +The library supports the following [choice restrictions](http://hl7.org/fhir/uv/sdc/behavior.html#choice-restriction). Note some of these are already covered in [Questionnaire item](#questionnaire-item) support. + +| Choice restriction | Support | Notes | +|:---------------------|:-------:|:--------------------------------| +| answerOption | ✅ | | +| answerValueSet | ✅ | | +| answerExpression | ✅ | | +| required | ✅ | | +| repeats | ✅ | | +| readOnly | ✅ | | +| minOccurs | ⛔️ | | +| maxOccurs | ⛔️ | | +| optionExclusive | ✅ | | +| unitOption | ⛔️ | | +| unitValueSet | ⛔️ | | +| referenceResource | ⛔️ | | +| referenceProfile | ⛔️ | | +| candidateExpression | ✅ | | +| lookupQuestionnaire | ⛔️ | | + +#### Calculations + +| Code | Support | Example | Notes | +|:---------------------|:-------:|:--------|:-----------------------------------| +| cqf-library | ⛔️ | | | +| launchContext | ✅ | | | +| variable | ✅ | | | +| initialExpression | ✅ | | | +| calculatedExpression | ✅ | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/behavior_calculated_expression.json) | +| cqf-calculatedValue | ⛔️ | | | +| cqf-expression | ⚠️ | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/behavior_dynamic_question_text.json) | `text` only | + +#### Other control + +| Code | Support | Notes | +|:---------------------|:-------:|:-----------------------------------| +| entryMode | ✅ | | +| intial | ✅ | | +| enableWhen | ✅ | | +| enableWhenBehavior | ✅ | | +| enableWhenExpression | ✅ | | +| usageMode | ⛔️ | | +| constraint | ⛔️ | | +| endpoint | ⛔️ | | +| signatureRequired | ⛔️ | | +| ordinalValue | ⛔️ | | +| text | ⛔️ | | + +## Expression extensions + +This section summarizes the library's support for [expressions](http://build.fhir.org/ig/HL7/sdc/expressions.html). + +| Name | Support | Example | Notes | +| ---------------------------- | :-----: | :------ | ----------------------------------------------------------- | +| variable | ✅ | | | +| answerExpression | ✅ | | | +| initialExpression | ✅ | | | +| candidateExpression | ⚠️ | | [#1038](https://github.com/google/android-fhir/issues/1038) | +| contextExpression | ⛔️ | | | +| calculatedExpression | ✅ | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/behavior_calculated_expression.json) | | +| enableWhenExpression | ✅ | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/behavior_skip_logic.json) | | +| answerOptionToggleExpression | ⛔️ | | | +| itemPopulationContext | ⛔️ | | | +| itemExtractionContext | ⛔️ | | | +| constraint | ⛔️ | | | +| library | ⛔️ | | [#1060](https://github.com/google/android-fhir/issues/1060) | +| launchContext | ✅ | | | diff --git a/docs/use/SDCL/Getting-Started.md b/docs/use/SDCL/Getting-Started.md new file mode 100644 index 0000000000..3d20bf0718 --- /dev/null +++ b/docs/use/SDCL/Getting-Started.md @@ -0,0 +1,179 @@ +# Getting Started + +This page describes how to configure an Android Studio project to use the +Structured Data Capture Library, and simple examples of how to use the library. + +This guide is intended for developers who are familiar with basic Android +development with Kotlin, and proficient in working with +[FHIR](http://hl7.org/fhir/) concepts and resources. + +## Dependencies + +The Structured Data Capture Library is available through +[Google's Maven repository](https://maven.google.com/web/index.html), which +should be already configured for Android projects created in Android Studio 3.0 +and higher. + +Add the following dependencies to your module's app-level `build.gradle` file, +typically `app/build.gradle`: + +```gradle +dependencies { + // ... + + implementation 'com.google.android.fhir:data-capture:1.0.0' + implementation 'androidx.fragment:fragment-ktx:1.5.5' +} +``` + +The minimum API level supported is 24. The library also requires +[Android Gradle Plugin](https://developer.android.com/studio/releases/gradle-plugin) +version 4.0.0 or later for +[Java 8+ API desugaring support](https://developer.android.com/studio/write/java8-support#library-desugaring). + +The following examples assume you already have a +[FHIR questionnaire](https://www.hl7.org/fhir/questionnaire.html) as a JSON +file. If you need one, the FHIR specification has +[several examples](https://www.hl7.org/fhir/questionnaire-examples.html) like +[this one](https://www.hl7.org/fhir/questionnaire-example-f201-lifelines.json). + +## Display a Questionnaire + +`QuestionnaireFragment` is the interface for working with +[FHIR questionnaires](https://www.hl7.org/fhir/questionnaire.html), and also a +[fragment](https://developer.android.com/guide/fragments) for rendering them. +See the QuestionnaireFragment guide for details. To render a questionnaire in +your app, follow these steps: + +1. Add a `FragmentContainerView` to your activity's layout to contain the + Questionnaire. + + ```xml + + + + + + + ``` + +1. Create a bundle with the JSON questionnaire content for the fragment, in + this case as a `String` read from a JSON file stored in the `assets` folder. + + ```kotlin + // Small questionnaires can be read directly as a string, larger ones + // should be passed as a URI instead. + val questionnaireJsonString = + application.assets.open("questionnaire.json") + .bufferedReader().use { it.readText() } + + val bundle = bundleOf( QuestionnaireFragment.EXTRA_QUESTIONNAIRE_JSON_STRING to + questionnaireJsonString ) + ``` + +1. Set the fragment to the `FragmentContainerView`. + + ```kotlin + if (savedInstanceState == null) { + supportFragmentManager.commit { + setReorderingAllowed(true) + add(R.id.fragment_container_view, args = bundle) + } + } + ``` + +## Get a QuestionnaireResponse + +The `getQuestionnaireResponse` function of `QuestionnaireFragment` returns the +current form answers in a +[FHIR QuestionnaireResponse](http://www.hl7.org/fhir/questionnaireresponse.html), +specifically as an instance of the +[HAPI FHIR Structures data model's QuestionnaireResponse](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/QuestionnaireResponse.html). +This provides a +[convenient interface](https://hapifhir.io/hapi-fhir/docs/model/working_with_resources.html) +to work with the data: + +```kotlin +val fragment: QuestionnaireFragment = + supportFragmentManager.findFragmentById(R.id.fragment_container_view) as QuestionnaireFragment +val questionnaireResponse = fragment.getQuestionnaireResponse() + +// For example, convert the whole response to a string +val questionnaireResponseString = context.newJsonParser().encodeResourceToString(questionnaireResponse) +Log.d( + "response", questionnaireResponseString +) +``` + +This could be in a callback for the user after pressing a Submit button. + +## Extract FHIR Resources from a QuestionnaireResponse + +`ResourceMapper` converts data between a QuestionnaireResponse and other FHIR +resources by implementing data +[extraction](http://build.fhir.org/ig/HL7/sdc/extraction.html) and +[population](http://build.fhir.org/ig/HL7/sdc/populate.html) from the +[HL7 Structured Data Capture Implementation Guide](http://build.fhir.org/ig/HL7/sdc/). +See the ResourceMapper guide for more information. + +The Structured Data Capture Library supports two mechanisms for data extraction: +[Definition-based extraction](http://hl7.org/fhir/uv/sdc/extraction.html#definition-based-extraction) +and +[StuctureMap-based extraction](http://hl7.org/fhir/uv/sdc/extraction.html#structuremap-based-extraction). + +Both methods require a `Questionnaire` and corresponding +`QuestionnaireResponse`: + +```kotlin +val jsonParser = FhirContext.forCached(FhirVersionEnum.R4).newJsonParser() + +val myQuestionnaire = + jsonParser.parseResource(questionnaireJson) as Questionnaire + +// also need the QuestionnaireResponse, probably like this +val myQuestionnaireResponse = fragment.getQuestionnaireResponse() +``` + +For Definition-based extraction, just pass the `Questionnaire` and +`QuestionnaireResponse` to `ResourceMapper.extract()`. + +```kotlin +lifecycle.coroutineScope.launch { + val bundle = + ResourceMapper.extract(questionnaire, questionnaireResponse) +} +``` + +StructureMap-based Extraction also requires a `StructureMapExtractionContext` +that contains the StructureMap. For example, if your StructureMap is written in +the [FHIR Mapping Language](http://hl7.org/fhir/R4/mapping-language.html): + +```kotlin +val mappingStr = "map ..." +lifecycle.coroutineScope.launch { + val bundle = + ResourceMapper.extract( + myQuestionnaire, + myQuestionnaireResponse, + StructureMapExtractionContext(context = applicationContext) { _, worker -> + StructureMapUtilities(worker).parse(mappingStr, "") + }, + ) +} +``` + +The `extract` function is a suspend function, so these examples must be called +from an appropriate +[coroutine](https://developer.android.com/kotlin/coroutines). + +## Further reading + +* [Use QuestionnaireFragment](Use-QuestionnaireFragment.md) +* [Use ResourceMapper](Use-ResourceMapper.md) +* [Customize how a Questionnaire is displayed](Customize-how-a-Questionnaire-is-displayed.md) +* [Reference external data](Reference-external-data.md) diff --git a/docs/use/SDCL/Reference-external-data.md b/docs/use/SDCL/Reference-external-data.md new file mode 100644 index 0000000000..dee42706d7 --- /dev/null +++ b/docs/use/SDCL/Reference-external-data.md @@ -0,0 +1,33 @@ +# Reference external data + +A questionnaire may reference external information. If so, you must provide a `DataCaptureConfig` by implementing the `DataCaptureConfig.Provider` interface in your application's [Application](https://developer.android.com/reference/android/app/Application) class. Be sure to provide the same configuration throughout your application's lifecycle to avoid any configuration issues. + +## Value sets + +If a value set is not included as a [contained resource](http://www.hl7.org/fhir/references.html#contained) within the questionnaire or structure map that references it, you must provide an implementation of `ExternalAnswerValueSetResolver.resolve()` which describes how to translate a value set's canonical URL to the list of actual codes: + +``` +class FhirApplication : Application(), DataCaptureConfig.Provider { + + private val dataCaptureConfiguration by lazy { + DataCaptureConfig( + valueSetResolverExternal = + object : ExternalAnswerValueSetResolver { + override suspend fun resolve(uri: String): List { + return lookupCodesFromDb(uri) + } + } + ) + } + + override fun getDataCaptureConfig(): DataCaptureConfig { + return dataCaptureConfiguration + } +} +``` + +`ExternalAnswerValueSetResolver` is used for any URI that does not look like an internal reference where the URI starts with `#`. + +## FHIR NPM packages + +FHIR resources published in [FHIR Packages](https://confluence.hl7.org/display/FHIR/NPM+Package+Specification) can be used to provide context while performing StructureMap-based data extraction. diff --git a/docs/use/SDCL/Use-QuestionnaireFragment.md b/docs/use/SDCL/Use-QuestionnaireFragment.md new file mode 100644 index 0000000000..81a7d4e02a --- /dev/null +++ b/docs/use/SDCL/Use-QuestionnaireFragment.md @@ -0,0 +1,181 @@ +# Use `QuestionnaireFragment` + +`QuestionnaireFragment` is the main interface for displaying FHIR Questionnaires +and getting user responses as FHIR QuestionnareResponses. In this section, we +will discuss how to use `QuestionnaireFragment` in more detail. To use +`QuestionnaireFragment` effectively, you should also be familiar with using +[Fragments in Android](https://developer.android.com/guide/fragments). + +## Display a Questionnaire in your application + +Place a `QuestionnaireFragment` in your activity or fragment whenever you want +to display a questionnaire. First, add a FragmentContainerView to your +activity's layout to contain the rendered Questionnaire, as shown in the +following example: + +```xml + +``` + +Next, define the content of the FHIR Questionnaire to render. The Questionnaire +must be JSON-encoded and can be provided as a `String` or a `URI` to a JSON +file. These values are provided in `QuestionnaireFragment.Builder` used to create a +`QuestionnaireFragment`. + +The following example reads a file in the `assets/` directory to a `String` which will be passed to the `QuestionnaireFragment`. + +```kotlin +val questionnaire: String = + application.assets.open("questionnaire.json").bufferedReader().use { it.readText() } +``` + +Providing a `String` is only suitable for Questionnaires that are a few KBs in +size, or +[you may get a TransactionTooLargeException exception](https://developer.android.com/guide/components/activities/parcelables-and-bundles#sdba). +For larger FHIR Questionnaires, use the URI-based option below. + +Alternatively, you may use a `URI` pointing to a JSON file containing the +questionnaire. The example below creates a `URI` for a questionnaire file stored +as a raw resource. + +```kotlin +val questionnaire: Uri = + Uri.parse("android.resource://" + this.packageName + "/" + R.raw.questionnaire) +``` + +How you get or create a `URI` for your questionnaire will depend on your data +source. You cannot get a `URI` for a file in the `assets/` directory. However, +you can use the following code to create a temporary copy and get a `URI` for +it. + +```kotlin +/** +* Returns a [Uri] pointing to a temporary file containing the content of the asset file with +* [filename]. +*/ +private suspend fun createUri(filename: String) = + withContext(backgroundContext) { + val application = getApplication() + val outputFile = File(application.externalCacheDir, filename) + application.assets.open(filename).use { inputStream -> + outputFile.outputStream().use { outputStream -> IOUtils.copy(inputStream, outputStream) } + } + Uri.fromFile(outputFile) + } +``` + +Use `QuestionnaireFragment.Builder` to create the `QuestionnaireFragment`. You must call one of `setQuestionnaire(questionnaireJson: String)` or +`setQuestionnaire(questionnaireUri: Uri)` in `QuestionnaireFragment.Builder`. If neither is provided, the system throws an `IllegalStateException` exception. If +both are provided, `setQuestionnaire(questionnaireUri: Uri)` takes precedence and +`setQuestionnaire(questionnaireJson: String)` is ignored. + +In a real application, the FHIR Questionnaire JSON can be loaded from a file +(like in the examples above), a database, the network, or even hardcoded, +depending on your use case. If you are using any I/O operations to load the +JSON, it should be done asynchronously such as by using +[coroutines](https://developer.android.com/kotlin/coroutines). + +Finally, use +[FragmentManager](https://developer.android.com/guide/fragments/fragmentmanager) +to programmatically set the fragment to the FragmentContainerView. + +```kotlin +if (savedInstanceState == null) { + supportFragmentManager.commit { + setReorderingAllowed(true) + add( + R.id.fragment_container_view, + QuestionnaireFragment.builder().setQuestionnaire(questionnaire).build(), + QUESTIONNAIRE_FRAGMENT_TAG + ) + } +} +``` + +This example shows the minimal code to +[add a fragment programmatically](https://developer.android.com/guide/fragments/create#add-programmatic), +but Android strongly recommends using the +[Navigation library](https://developer.android.com/guide/navigation) to manage +navigation in a real app. + +## Collect a Questionnaire response + +Once the user has finished filling out the questionnaire, you can collect the +questionnaire response. Typically you should use `FragmentManager` to find your +questionnaire fragment and then call `getQuestionnaireResponse()`. + +```kotlin +val fragment: QuestionnaireFragment = + supportFragmentManager.findFragmentById(R.id.fragment_container_view) as QuestionnaireFragment +val questionnaireResponse = fragment.getQuestionnaireResponse() +``` + +The form answers are structured as a +[FHIR QuestionnaireResponse](http://www.hl7.org/fhir/questionnaireresponse.html), +which is a structured set of answers to the questions in the corresponding FHIR +Questionnaire. More specifically, it an instance of +[org.hl7.fhir.r4.model.QuestionnaireResponse](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/QuestionnaireResponse.html), +a class in the [HAPI FHIR](https://hapifhir.io/) +[Structures library](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-structures-r4/) +which is used as the in-memory data model for FHIR resources in the SDK. This +provides a relatively convenient interface to work with the data: + +```kotlin +// Get the first answer for the first item +val questionnaireResponseFirstAnswer = + questionnaireResponse.item[0].answer[0].value.asStringValue() + +// Convert the whole response to a JSON string and send to log +val jsonParser = FhirContext.forCached(FhirVersionEnum.R4).newJsonParser() +val questionnaireResponseString = jsonParser.encodeResourceToString(questionnaireResponse) +Log.d( "response", questionnaireResponseString) + +``` + +Learn more about +[working with HAPI FHIR resources](https://hapifhir.io/hapi-fhir/docs/model/working_with_resources.html). + +What you do with the questionnaire response depends on your use case: + +* If your existing application does not store data using FHIR, you can + navigate the response's item and answer structure to get and store responses + in your app's native format. +* If the questionnaire you are using implements + [form data extraction](http://build.fhir.org/ig/HL7/sdc/extraction.html), + you can use Structured Data Capture Library's `ResourceMapper` to extract + additional FHIR resources based on the questionnaire response. + +## Pre-fill a questionnaire with existing answers + +If you want your questionnaire to start with some answers already filled, +include a questionnaire response in your arguments bundle for your +`QuestionnaireFragment`. + +```kotlin +val questionnaireFragment = + QuestionnaireFragment.builder() + .setQuestionnaire(questionnaire) + .setQuestionnaireResponse(questionnaireResponse) + .build() +``` + +This may be useful if, for example, you allow a user to edit a form they have +previously submitted, or to pre-fill certain fields where you already know the +value based on another source. + +Provide one of `setQuestionnaire(questionnaireJson: String)` or +`setQuestionnaire(questionnaireUri: Uri)` in the QuestionnaireFragment.Builder. + If both are provided, `setQuestionnaire(questionnaireUri: Uri)` takes precedence and +`setQuestionnaire(questionnaireJson: String)` is ignored. + +Similar to questionnaires, do not pass questionnaire responses over a few KBs in +size as a `String` in `setQuestionnaireResponse(questionnaireResponseJson: String)`, + but instead provide a `URI` using `setQuestionnaireResponse(questionnaireResponseUri: Uri)`. + +## Further reading + +* [Customize how a questionnaire is displayed](Customize-how-a-Questionnaire-is-displayed.md) diff --git a/docs/use/SDCL/Use-QuestionnaireResponseValidator.md b/docs/use/SDCL/Use-QuestionnaireResponseValidator.md new file mode 100644 index 0000000000..94a931c588 --- /dev/null +++ b/docs/use/SDCL/Use-QuestionnaireResponseValidator.md @@ -0,0 +1,7 @@ +# Use `QuestionnaireResponseValidator` + +The Structured Data Capture Library provides an API to validate a FHIR QuestionnaireResponse resource against the FHIR Questionnaire resource it is answering. + +```kotlin +val validationResult = QuestionnaireResponseValidator.validate(questionnaire, questionnaireResponse, context) +``` diff --git a/docs/use/SDCL/Use-ResourceMapper.md b/docs/use/SDCL/Use-ResourceMapper.md new file mode 100644 index 0000000000..d42d6a6f28 --- /dev/null +++ b/docs/use/SDCL/Use-ResourceMapper.md @@ -0,0 +1,157 @@ +# Use `ResourceMapper` + +Mapping FHIR Questionnaire Responses to other FHIR resources (and back) allows +the structured data capture process to be more tightly integrated with clinical +workflows. + +For example, if your application has a questionnaire for new patient +registration, your ultimate goal may be to create a +[FHIR Patient resource](https://www.hl7.org/fhir/patient.html) based on the +answers provided to use in your application. Or, if your application has a +questionnaire for entering test results, you could create a FHIR Observation +resource. The process of mapping a FHIR QuestionnaireResponse to one or more +other FHIR resources is called +[extraction](http://hl7.org/fhir/uv/sdc/extraction.html). + +On the other hand, you may want to reduce data entry by loading values from +existing FHIR resources into your questionnaire. For example, if a questionnaire +asks for a patient's name and age, you can pre-populate that information from an +existing FHIR Patient resource. The process of mapping one or more FHIR +resources to a FHIR QuestionnaireResponse is called +[population](http://hl7.org/fhir/uv/sdc/populate.html). + +This section shows how to use the +[`ResourceMapper`](https://github.com/google/android-fhir/blob/master/datacapture/src/main/java/com/google/android/fhir/datacapture/mapping/ResourceMapper.kt) +class from the Structured Data Capture Library to perform extraction and +population. + +## Extract FHIR resources from a questionnaire response + +The Structured Data Capture Library supports two mechanisms for data extraction: +[Definition-based extraction](http://hl7.org/fhir/uv/sdc/extraction.html#definition-based-extraction) +and +[StuctureMap-based extraction](http://hl7.org/fhir/uv/sdc/extraction.html#structuremap-based-extraction). + +Both methods of extraction require a HAPI FHIR `Questionnaire` that includes +data extraction FHIR extensions, plus a corresponding `QuestionnaireResponse` +containing the answers to extract. You can use HAPI FHIR's +[`JsonParser.parseResource()`](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/parser/JsonParser.html#parseResource\(ca.uhn.fhir.parser.json.JsonLikeStructure\)) +from +[`FhirContext.newJsonParser()`](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-base/ca/uhn/fhir/context/FhirContext.html#newJsonParser\(\)) +to deserialize your JSON content to a questionnaire: + +```kotlin +val jsonParser = FhirContext.forCached(FhirVersionEnum.R4).newJsonParser() + +// From a JSON string +val myQuestionnaire = + jsonParser.parseResource(questionnaireJsonString) as Questionnaire + +// From a URI for a JSON file +val myQuestionnaire = + jsonParser.parseResource(contentResolver.openInputStream(questionnaireUri)) as Questionnaire +``` + +The `QuestionnaireResponse` you use with data extraction is likely from calling +`QuestionnaireFragment.getQuestionnaireResponse()` after your user fills out a +questionnaire: + +```kotlin +val myQuestionnaireResponse = fragment.getQuestionnaireResponse() +``` + +[Learn more about QuestionnaireFragment](Use-QuestionnaireFragment.md) +and how to collect responses from a questionnaire. + +Next, call `ResourceMapper.extract()` to extract the FHIR resources. It returns +a +[HAPI FHIR Bundle](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/Bundle.html) +containing one or more FHIR resources as specified by the data extraction FHIR +extensions in the questionnaire. Note that `ResourceMapper.extract()` is a +suspend function, so the following examples must be called from an appropriate +[coroutine](https://developer.android.com/kotlin/coroutines), such as +[`ViewModelScope` if you are using a ViewModel in your app](https://medium.com/androiddevelopers/easy-coroutines-in-android-viewmodelscope-25bffb605471). + +### Definition-based extraction + +For Definition-based extraction, all the metadata required to perform data +extraction are within the questionnaire, so no additional information is +necessary. Simply pass the `Questionnaire` and `QuestionnaireResponse` to +`ResourceMapper.extract()`: + +```kotlin +val bundle = ResourceMapper.extract(questionnaire, questionnaireResponse) +``` + +### StructureMap-based extraction + +In addition to the Questionnaire and QuestionnaireResponse, StructureMap-based +Extraction also requires a `StructureMapExtractionContext` to retrieve a +StructureMap. To create a `StructureMapExtractionContext`, pass your +application's context and provide a `structureMapProvider` lambda function which +returns the `StructureMap`. + +The function includes a String parameter which contains the canonical URL for +the Structure Map referenced in the +[Target structure map extension](http://hl7.org/fhir/uv/sdc/StructureDefinition-sdc-questionnaire-targetStructureMap.html) +of the questionnaire, and a HAPI FHIR +[`IWorkerContext`](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/context/IWorkerContext.html) +which may be used with other HAPI FHIR classes, like +[`StructureMapUtilities`](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/utils/StructureMapUtilities.html). + +A StructureMap may be written in the +[FHIR Mapping Language](http://hl7.org/fhir/R4/mapping-language.html) or as a +[StructureMap FHIR resource](http://hl7.org/fhir/R4/structuremap.html). + +For example, if your StructureMap is hard-coded and written in the FHIR Mapping +Language: + +```kotlin +val mappingStr = "map ..." +val bundle = ResourceMapper.extract( + myQuestionnaire, + myQuestionnaireResponse, + StructureMapExtractionContext(context = applicationContext) { _, worker -> + StructureMapUtilities(worker).parse(mapping, "") + }, +) +``` + +As another example, this code uses a StructureMap resource as JSON based on its +URL: + +```kotlin +val bundle = ResourceMapper.extract( + myQuestionnaire, + myQuestionnaireResponse, + StructureMapExtractionContext(context = applicationContext) { targetStructureMapUrl, _ -> + val structureMapJson = getJsonFromUrl(targetStructureMapUrl) + jsonParser.parseResource(mappingJson) as StructureMap + ) + }, +) +``` + +## Populate a questionnaire response based on other FHIR resources + +The Structured Data Capture Library supports +[expression-based population](http://hl7.org/fhir/uv/sdc/populate.html#expression-based-population). +If a questionnaire implements the +[SDC Questionnaire Populate - Expression profile](http://hl7.org/fhir/uv/sdc/StructureDefinition-sdc-questionnaire-pop-exp.html), +then you can use `ResourceMapper.populate()` to generate a questionnaire +response based on the values in other FHIR resources: + +```kotlin +val questionnaireResponse = ResourceMapper.populate(questionnaire, resource1, resource2, ...) +``` + +In this example, `resource1, resource2, ...` are FHIR resources represented by +instances of +[HAPI FHIR Structures](https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/package-summary.html). +To understand which resources you should include, look at the expression-based +population extensions used in the questionnaire, most often the +[Initial Expression extension](https://hl7.org/fhir/uv/sdc/StructureDefinition-sdc-questionnaire-initialExpression.html). + +`ResourceMapper.populate()` returns a `QuestionnaireResponse` which can be used +to +[pre-fill a questionnaire with existing answers](Use-QuestionnaireFragment.md#pre-fill-a-questionnaire-with-existing-answers). diff --git a/docs/use/SDCL/index.md b/docs/use/SDCL/index.md new file mode 100644 index 0000000000..b731e0302f --- /dev/null +++ b/docs/use/SDCL/index.md @@ -0,0 +1,30 @@ +# What is the Structured Data Capture Library? + +The Structured Data Capture Library lets you easily build Android applications that capture and process healthcare data using the [FHIR Questionnaire](https://www.hl7.org/fhir/questionnaire.html). + +## Key Capabilities + +* **Render FHIR Questionnaires** Displays the questionnaire for you in a [Fragment](https://developer.android.com/guide/fragments) using consistent, [Material](https://material.io/)-based components +* **Standards-based form responses** Answers are consistently formatted as a [FHIR QuestionnaireResponse](http://www.hl7.org/fhir/questionnaireresponse.html) +* **Validate answers** Validate individual fields during user entry or entire questionnaire responses +* **Extract additional FHIR resources** Convert the QuestionnaireResponse to other FHIR resources to populate a FHIR-based health record +* **Powerful form controls** Advanced rendering and form behaviors such as skip-logic, pagination, runtime validation and multi-language support based on the [HL7 Structured Data Capture](http://build.fhir.org/ig/HL7/sdc/) implementation guide +* **Custom look and feel** Supports custom themes or creating your own question widgets + +## Why would you use the Structured Data Capture Library? + +Forms to collect data are a very common component of healthcare applications today. When building a typical Android application you need to design and code the business logic and UI for each form you create. This quickly becomes unsustainable for the many different forms used in a modern healthcare environment. + +With the Structured Data Capture Library, forms are defined using a [FHIR Questionnaire](https://www.hl7.org/fhir/questionnaire.html) and rendered for you. This separates form design from application development, allowing forms to be easily added, shared, and updated without building UI layouts, and healthcare data experts can author questionnaires without any knowledge of Android development. + +The Structured Data Capture Library also simplifies the process of creating FHIR resources based on form answers and using existing FHIR data to pre-populate forms. These two processes make data collected using FHIR Questionnaires more meaningful and useful in clinical workflows and enable more advanced use cases. + +## How does the Structured Data Capture Library work? + +There are three main public APIs in the Structured Data Capture Library: + +* [QuestionnaireFragment](Use-QuestionnaireFragment.md): the main class for rendering questionnaires +* [ResourceMapper](Use-ResourceMapper.md): handles data extraction and questionnaire population +* [QuestionnaireResponseValidator](Use-QuestionnaireResponseValidator.md): validates questionnaire responses against questionnaires + +You can also browse the pages in the navigation sidebar for more information. diff --git a/docs/use/SDCL/sdc-lib-intro-1.png b/docs/use/SDCL/sdc-lib-intro-1.png new file mode 100644 index 0000000000000000000000000000000000000000..138f827c0282b6966e4bfcbadbdc057d590d9b18 GIT binary patch literal 41781 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
|2wN1k=3 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 literal 0 HcmV?d00001 diff --git a/docs/use/SDCL/sdc-ref-dropdown.png b/docs/use/SDCL/sdc-ref-dropdown.png new file mode 100644 index 0000000000000000000000000000000000000000..3b0bb062f96e4f2e6137765fdeefab349fe33a91 GIT binary patch literal 49943 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 yrxEM!31zz?bhS;2hJ-2 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 NO + +``` + +## Use FhirOperator APIs + +**1. Evaluate Individual Subject Matters:** + +```kotlin +fhirOperator.evaluateMeasure( + url = "http://fhir.org/guides/who/anc-cds/Measure/ANCIND01", + start = "2020-01-01", + end = "2020-01-31", + reportType = "subject", + subject = "charity-otala-1", + practitioner = "jane", + lastReceivedOn = null +) +``` + +**2. Evaluate Population Matters:** + +```kotlin +val measureReport : MeasureReport = + fhirOperator.evaluateMeasure( + url = "http://fhir.org/guides/who/anc-cds/Measure/ANCIND01", + start = "2019-01-01", + end = "2021-12-31", + reportType = "population", + subject = null, + practitioner = "jane", + lastReceivedOn = null + ) +``` + +**3. Generate Care Plan for a Patient:** + +```kotlin +val plan: CarePlan = fhirOperator.generateCarePlan( + planDefinitionId = "plandefinition-RuleFilters-1.0.0", + patientId = "Reportable", + encounterId = "reportable-encounter" +) +``` + +See [FhirOperatorTest.kt](https://github.com/google/android-fhir/blob/master/workflow/src/test/java/com/google/android/fhir/workflow/FhirOperatorTest.kt) for more details on how to set up data. diff --git a/docs/use/WFL/index.md b/docs/use/WFL/index.md new file mode 100644 index 0000000000..3681c450ed --- /dev/null +++ b/docs/use/WFL/index.md @@ -0,0 +1,28 @@ +# Workflow Library + +The [Workflow](https://build.fhir.org/workflow.html) Library provides decision support logic and analytics in clinical workflows. Authors of digital guidelines develop reports ([Measure](https://build.fhir.org/measure.html)) and individualized clinical procedures ([PlanDefinition](https://build.fhir.org/plandefinition.html)) to be run on FHIR Databases. Both assets rely on [FHIR Libraries](https://build.fhir.org/library.html) that can be written in [Clinical Quality Language](https://cql.hl7.org/) or [FhirPath](https://hl7.org/fhir/fhirpath.html). To execute such workflows, this library implements the two major FHIR operations, Measure [$Evaluate](https://build.fhir.org/operation-measure-evaluate-measure.html) and Plan Definition [$Apply](https://build.fhir.org/plandefinition-operation-apply.html), as well as the lower-level Library [$Evaluate](https://build.fhir.org/ig/HL7/cqf-recommendations/OperationDefinition-cpg-library-evaluate.html) operation: + +1. The [Measure](https://build.fhir.org/measure.html) resource is a reporting-definition tool that supports the evaluation of clinical measures, such as the percentage of patients who received a recommended screening or the number of patients with a specific condition who received appropriate treatment. The output of this operation will be a Report resource, which includes the results of the evaluation. The Report resource will include details about the individual measures that were evaluated, the scores for those measures, and any relevant supporting information. It may also include references to other resources that are relevant to the evaluation, such as observations or procedures that were used to calculate the measure scores. These calculations can be used to assess the performance of a healthcare provider or organization and can help identify areas for improvement. + +1. The [PlanDefinition](https://build.fhir.org/plandefinition.html) resource describes a plan or protocol for the care of a given patient. This could include a treatment plan for a specific condition, a discharge plan for a hospitalized patient, or a care plan for managing chronic illness. The output of this operation will be a CarePlan resource, which represents the plan that has been tailored and applied to the specific patient or group of patients. The CarePlan resource will include details about the actions that are part of the plan, the timing and frequency of those actions, and any relevant supporting information. It may also include references to other resources that are relevant to the plan, such as observations or procedures that are part of the plan. The Apply operator can be used to determine the specific actions or interventions that should be taken as part of a care plan, based on the patient's current status and other relevant factors. For example, it could be used to determine which medications a patient should be prescribed or to identify any necessary referrals to other healthcare providers. + +1. The [Library](https://build.fhir.org/library.html) resource describes a container for clinical knowledge assets. One of these assets is a shareable library of clinical logic, written in Clinical Quality Language (CQL). Users of the Workflow library can call an evaluation operator directly from the Library resource and run individual expressions at will. The output will be Parameters resource with the results of each expression evaluated. This operator should be used when the use case does not fit into a PlanDefinition or a Measure Evaluate. + +It's recommended that these 3 types of resources are authored within the scope of a [FHIR IG](https://www.hl7.org/fhir/implementationguide.html). The IG can then be published online and imported by the Android SDK. To import an IG, Android SDK users must simply copy the required files from the IG package into the `assets` folder and parse those files using the regular FHIR Parser. + +The workflow library is dependent on the [Engine library](../FEL/index.md). Operations execute over the dataset saved in the FhirEngine instance. + +Future features of the library will provide support for Tasking and other Workflow related requirements + +## Next Steps + +* [Getting Started](Getting-Started.md) +* Guides + * [Generate a Care Plan](Generate-A-Care-Plan.md) + * [Evaluate a Measure](Evaluate-a-Measure.md) + * [Evaluate a Library](Evaluate-a-Library.md) + * [Compile CQL](Compile-and-Execute-CQL.md) + +## Data safety + +This library does not collect or share any personal or sensitive [user data](https://developer.android.com/guide/topics/data/collect-share) with any third party libraries or SDKs. diff --git a/mkdocs.yaml b/mkdocs.yaml index d87165d321..ea6ca45351 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -6,11 +6,48 @@ copyright: Copyright 2024 The Android FHIR SDK Authors nav: - Home: index.md + - faq.md - Users: - - API: use/api.md + - FHIR Engine Library: + - Introduction: use/FEL/index.md + - Getting Started: use/FEL/Getting-started.md + - Guides: + - use/FEL/Manage-FHIR-resources-locally.md + - use/FEL/Search-FHIR-resources.md + - use/FEL/Sync-data-with-FHIR-server.md + - use/FEL/Privacy-Security.md + - use/FEL/Demo-app.md + - Reference: + - use/FEL/FHIR-search-specification-support.md + - Structured Data Capture Library: + - Introduction: use/SDCL/index.md + - Getting Started: use/SDCL/Getting-Started.md + - Guides: + - use/SDCL/Use-QuestionnaireFragment.md + - use/SDCL/Use-QuestionnaireResponseValidator.md + - use/SDCL/Use-ResourceMapper.md + - use/SDCL/Customize-how-a-Questionnaire-is-displayed.md + - use/SDCL/Reference-external-data.md + - use/SDCL/Author-questionnaires.md + - Demo App: use/SDCL/Demo-app.md + - Reference: + - FHIR specification support: use/SDCL/FHIR-specification-support.md + - Workflow Library: + - Introduction: use/WFL/index.md + - use/WFL/Getting-Started.md + - Guides: + - use/WFL/Generate-A-Care-Plan.md + - use/WFL/Evaluate-a-Measure.md + - use/WFL/Evaluate-a-Library.md + - use/WFL/Compile-and-Execute-CQL.md + - use/Extensions.md + - API Doc: use/api.md - Contributors: - - Codespaces: contrib/codespaces.md - - Documentation: contrib/docs.md + - Contributing: contrib/index.md + - Codespaces: contrib/codespaces.md + - Documentation: contrib/docs.md + - contrib/dependencies.md + - Roadmap: contrib/roadmap.md # The following settings were originally partially inspired by # https://github.com/enola-dev/enola/blob/main/mkdocs.yaml @@ -18,22 +55,22 @@ nav: theme: name: material features: - - content.action.edit - - content.code.copy - - navigation.expand - - navigation.footer - - navigation.instant - - navigation.tracking - - navigation.path - - navigation.top - - search.suggest - - search.share + - content.action.edit + - content.code.copy + - navigation.expand + - navigation.footer + - navigation.instant + - navigation.tracking + - navigation.path + - navigation.top + - search.suggest + - search.share plugins: - search - git-revision-date-localized - minify: - minify_html: true + minify_html: true # https://www.mkdocs.org/user-guide/configuration/#validation # Nota Bene: There is no "error" level in MkDocs, but the build-docs.bash script From 8e2aaf0002c8a75eb0e74665480aa552b9876580 Mon Sep 17 00:00:00 2001 From: Michael Vorburger Date: Wed, 22 May 2024 20:13:07 +0200 Subject: [PATCH 3/9] Fix broken images in migrated Wiki docs (#2549) --- docs/use/FEL/index.md | 8 +------- docs/use/SDCL/FHIR-specification-support.md | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/docs/use/FEL/index.md b/docs/use/FEL/index.md index 4f9570456f..ac4fada1e3 100644 --- a/docs/use/FEL/index.md +++ b/docs/use/FEL/index.md @@ -4,13 +4,7 @@ The _FHIR Engine Library_ is a Kotlin library that makes it easy to manage FHIR Today, there are a growing number of tools and software libraries supporting the use of [FHIR](https://www.hl7.org/fhir/) on various platforms. However, developer support for FHIR on Android is still lacking. Typically, Android healthcare applications still use proprietary data models, and as a result, suffer from a lack of interoperability. The FHIR Engine Library addresses this problem by provding a set of APIs to help manage FHIR resources on Android, allowing easier integration with other software systems using FHIR. -

-[[fhir-engine-components.png|width=640px]] -

- -

-Figure 1: FHIR Engine Library components -

+![FHIR Engine Library components](fhir-engine-components.png) ## FHIR Engine Library components diff --git a/docs/use/SDCL/FHIR-specification-support.md b/docs/use/SDCL/FHIR-specification-support.md index b446c73193..3cb7e9aad3 100644 --- a/docs/use/SDCL/FHIR-specification-support.md +++ b/docs/use/SDCL/FHIR-specification-support.md @@ -95,7 +95,7 @@ The [`itemControl`](https://build.fhir.org/ig/HL7/fhir-extensions/ValueSet-quest | Fly-over | Display | | | | Help-Button | Display | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_help.json) | | | | Auto-complete | Choice | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_auto_complete.json) | Filter-forward based on inlined answerOptions | | -| Drop down | Choice | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_dropdown.json) | Default for 4 or more answer options | [](sdc-ref-dropdown.png) | +| Drop down | Choice | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_dropdown.json) | Default for 4 or more answer options | ![Drop Down](sdc-ref-dropdown.png) | | Check-box | Choice | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_multi_select_choice.json) | Default for repeat answers | | | Radio Button | Choice | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_single_choice.json) | Default for less than 4 answer options | | | Slider | Integer | [JSON](https://github.com/google/android-fhir/blob/master/catalog/src/main/assets/component_slider.json) | | | From d83692eb3ada2e33869f384630add1a2acd05180 Mon Sep 17 00:00:00 2001 From: santosh-pingle <86107848+santosh-pingle@users.noreply.github.com> Date: Tue, 28 May 2024 13:09:31 +0530 Subject: [PATCH 4/9] Resource Creation using POST http verb (SingleResourcePost) (#2464) * draft singleresourcepost * Remove dead code. * resource consolidation after post http verb request * Remove local changes. * fix unit tests. * unit tests * Update kotlin api docs. * revert local changes. * Resource consolidation as per http verb * address review comments. * order of arguments * code to string conversion * Address review comments. * Fix version id and use existing api. * Address review comments. * Add unit tests. * Address review comments. --------- Co-authored-by: Santosh Pingle --- .../android/fhir/db/impl/DatabaseImplTest.kt | 4 +- .../HttpPostResourceConsolidatorTest.kt | 231 ++++++++++++++++++ .../com/google/android/fhir/FhirEngine.kt | 4 +- .../android/fhir/db/impl/dao/ResourceDao.kt | 1 + .../android/fhir/impl/FhirEngineImpl.kt | 12 +- .../android/fhir/sync/FhirSyncWorker.kt | 22 +- .../android/fhir/sync/FhirSynchronizer.kt | 27 +- .../fhir/sync/upload/ResourceConsolidator.kt | 123 ++++++++-- .../fhir/sync/upload/UploadStrategy.kt | 24 +- .../google/android/fhir/testing/Utilities.kt | 4 +- .../android/fhir/impl/FhirEngineImplTest.kt | 26 +- .../android/fhir/sync/FhirSynchronizerTest.kt | 5 +- .../upload/ResourceConsolidatorFactoryTest.kt | 50 ++++ 13 files changed, 456 insertions(+), 77 deletions(-) create mode 100644 engine/src/androidTest/java/com/google/android/fhir/sync/upload/HttpPostResourceConsolidatorTest.kt create mode 100644 engine/src/test/java/com/google/android/fhir/sync/upload/ResourceConsolidatorFactoryTest.kt diff --git a/engine/src/androidTest/java/com/google/android/fhir/db/impl/DatabaseImplTest.kt b/engine/src/androidTest/java/com/google/android/fhir/db/impl/DatabaseImplTest.kt index 16446abfdd..705b3c8a58 100644 --- a/engine/src/androidTest/java/com/google/android/fhir/db/impl/DatabaseImplTest.kt +++ b/engine/src/androidTest/java/com/google/android/fhir/db/impl/DatabaseImplTest.kt @@ -40,9 +40,9 @@ import com.google.android.fhir.search.getQuery import com.google.android.fhir.search.has import com.google.android.fhir.search.include import com.google.android.fhir.search.revInclude -import com.google.android.fhir.sync.upload.LocalChangesFetchMode import com.google.android.fhir.sync.upload.ResourceUploadResponseMapping import com.google.android.fhir.sync.upload.UploadRequestResult +import com.google.android.fhir.sync.upload.UploadStrategy.AllChangesSquashedBundlePut import com.google.android.fhir.testing.assertJsonArrayEqualsIgnoringOrder import com.google.android.fhir.testing.assertResourceEquals import com.google.android.fhir.testing.readFromFile @@ -552,7 +552,7 @@ class DatabaseImplTest { // Delete the patient created in setup as we only want to upload the patient in this test database.deleteUpdates(listOf(TEST_PATIENT_1)) services.fhirEngine - .syncUpload(LocalChangesFetchMode.AllChanges) { + .syncUpload(AllChangesSquashedBundlePut) { it .first { it.resourceId == "remote-patient-3" } .let { diff --git a/engine/src/androidTest/java/com/google/android/fhir/sync/upload/HttpPostResourceConsolidatorTest.kt b/engine/src/androidTest/java/com/google/android/fhir/sync/upload/HttpPostResourceConsolidatorTest.kt new file mode 100644 index 0000000000..67b1bb258c --- /dev/null +++ b/engine/src/androidTest/java/com/google/android/fhir/sync/upload/HttpPostResourceConsolidatorTest.kt @@ -0,0 +1,231 @@ +/* + * Copyright 2024 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.sync.upload + +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import ca.uhn.fhir.context.FhirContext +import com.google.android.fhir.FhirServices +import com.google.android.fhir.db.Database +import com.google.android.fhir.db.ResourceNotFoundException +import com.google.android.fhir.logicalId +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.runBlocking +import org.hl7.fhir.r4.model.DomainResource +import org.hl7.fhir.r4.model.InstantType +import org.hl7.fhir.r4.model.Observation +import org.hl7.fhir.r4.model.ResourceType +import org.junit.After +import org.junit.Assert.assertThrows +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized + +@RunWith(AndroidJUnit4::class) +class HttpPostResourceConsolidatorTest { + @JvmField @Parameterized.Parameter(0) var encrypted: Boolean = false + + private val context: Context = ApplicationProvider.getApplicationContext() + private lateinit var database: Database + private lateinit var resourceConsolidator: ResourceConsolidator + + @Before + fun setupDatabase() = runBlocking { + database = + FhirServices.builder(context) + .inMemory() + .apply { + if (encrypted) enableEncryptionIfSupported() + setSearchParameters(null) + } + .build() + .database + resourceConsolidator = HttpPostResourceConsolidator(database) + } + + @After + fun closeDatabase() { + database.close() + } + + @Test + fun consolidate_shouldUpdateResourceId() = runBlocking { + val patientJsonString = + """ + { + "resourceType": "Patient", + "id": "patient1" + } + """ + .trimIndent() + val patient = + FhirContext.forR4Cached().newJsonParser().parseResource(patientJsonString) as DomainResource + database.insert(patient) + val localChanges = database.getLocalChanges(patient.resourceType, patient.logicalId) + + val postSyncPatientJsonString = + """ + { + "resourceType": "Patient", + "id": "patient2", + "meta": { + "versionId": "1" + } + } + """ + .trimIndent() + val postSyncPatient = + FhirContext.forR4Cached().newJsonParser().parseResource(postSyncPatientJsonString) + as DomainResource + postSyncPatient.meta.lastUpdatedElement = InstantType.now() + val uploadRequestResult = + UploadRequestResult.Success( + listOf(ResourceUploadResponseMapping(localChanges, postSyncPatient)), + ) + resourceConsolidator.consolidate(uploadRequestResult) + + assertThat(database.select(ResourceType.Patient, "patient2").logicalId) + .isEqualTo(postSyncPatient.logicalId) + + val exception = + assertThrows(ResourceNotFoundException::class.java) { + runBlocking { database.select(ResourceType.Patient, "patient1") } + } + + assertThat(exception.message).isEqualTo("Resource not found with type Patient and id patient1!") + } + + @Test + fun consolidate_dependentResources_shouldUpdateReferenceValue() = runBlocking { + val patientJsonString = + """ + { + "resourceType": "Patient", + "id": "patient1" + } + """ + .trimIndent() + val patient = + FhirContext.forR4Cached().newJsonParser().parseResource(patientJsonString) as DomainResource + val observationJsonString = + """ + { + "resourceType": "Observation", + "id": "observation1", + "subject": { + "reference": "Patient/patient1" + } + } + """ + .trimIndent() + val observation = + FhirContext.forR4Cached().newJsonParser().parseResource(observationJsonString) + as DomainResource + database.insert(patient, observation) + val postSyncPatientJsonString = + """ + { + "resourceType": "Patient", + "id": "patient2", + "meta": { + "versionId": "1" + } + } + """ + .trimIndent() + val postSyncPatient = + FhirContext.forR4Cached().newJsonParser().parseResource(postSyncPatientJsonString) + as DomainResource + postSyncPatient.meta.lastUpdatedElement = InstantType.now() + val localChanges = database.getLocalChanges(patient.resourceType, patient.logicalId) + val uploadRequestResult = + UploadRequestResult.Success( + listOf(ResourceUploadResponseMapping(localChanges, postSyncPatient)), + ) + + resourceConsolidator.consolidate(uploadRequestResult) + + assertThat( + (database.select(ResourceType.Observation, "observation1") as Observation) + .subject + .reference, + ) + .isEqualTo("Patient/patient2") + } + + @Test + fun consolidate_localChanges_shouldUpdateReferenceValue() = runBlocking { + val patientJsonString = + """ + { + "resourceType": "Patient", + "id": "patient1" + } + """ + .trimIndent() + val patient = + FhirContext.forR4Cached().newJsonParser().parseResource(patientJsonString) as DomainResource + val observationJsonString = + """ + { + "resourceType": "Observation", + "id": "observation1", + "subject": { + "reference": "Patient/patient1" + } + } + """ + .trimIndent() + val observation = + FhirContext.forR4Cached().newJsonParser().parseResource(observationJsonString) + as DomainResource + database.insert(patient, observation) + val postSyncPatientJsonString = + """ + { + "resourceType": "Patient", + "id": "patient2", + "meta": { + "versionId": "1" + } + } + """ + .trimIndent() + val postSyncPatient = + FhirContext.forR4Cached().newJsonParser().parseResource(postSyncPatientJsonString) + as DomainResource + postSyncPatient.meta.lastUpdatedElement = InstantType.now() + val localChanges = database.getLocalChanges(patient.resourceType, patient.logicalId) + val uploadRequestResult = + UploadRequestResult.Success( + listOf(ResourceUploadResponseMapping(localChanges, postSyncPatient)), + ) + + resourceConsolidator.consolidate(uploadRequestResult) + + val localChange = database.getLocalChanges(ResourceType.Observation, "observation1").last() + assertThat( + (FhirContext.forR4Cached().newJsonParser().parseResource(localChange.payload) + as Observation) + .subject + .reference, + ) + .isEqualTo("Patient/patient2") + } +} diff --git a/engine/src/main/java/com/google/android/fhir/FhirEngine.kt b/engine/src/main/java/com/google/android/fhir/FhirEngine.kt index 45eb630896..fa47d2b21a 100644 --- a/engine/src/main/java/com/google/android/fhir/FhirEngine.kt +++ b/engine/src/main/java/com/google/android/fhir/FhirEngine.kt @@ -19,9 +19,9 @@ package com.google.android.fhir import com.google.android.fhir.db.ResourceNotFoundException import com.google.android.fhir.search.Search import com.google.android.fhir.sync.ConflictResolver -import com.google.android.fhir.sync.upload.LocalChangesFetchMode import com.google.android.fhir.sync.upload.SyncUploadProgress import com.google.android.fhir.sync.upload.UploadRequestResult +import com.google.android.fhir.sync.upload.UploadStrategy import java.time.OffsetDateTime import kotlinx.coroutines.flow.Flow import org.hl7.fhir.r4.model.Resource @@ -130,7 +130,7 @@ interface FhirEngine { */ @Deprecated("To be deprecated.") suspend fun syncUpload( - localChangesFetchMode: LocalChangesFetchMode, + uploadStrategy: UploadStrategy, upload: (suspend (List) -> Flow), ): Flow diff --git a/engine/src/main/java/com/google/android/fhir/db/impl/dao/ResourceDao.kt b/engine/src/main/java/com/google/android/fhir/db/impl/dao/ResourceDao.kt index 45786270bb..84458cf7a1 100644 --- a/engine/src/main/java/com/google/android/fhir/db/impl/dao/ResourceDao.kt +++ b/engine/src/main/java/com/google/android/fhir/db/impl/dao/ResourceDao.kt @@ -87,6 +87,7 @@ internal abstract class ResourceDao { resourceId = updatedResource.logicalId, serializedResource = iParser.encodeResourceToString(updatedResource), lastUpdatedRemote = updatedResource.meta.lastUpdated?.toInstant() ?: it.lastUpdatedRemote, + versionId = updatedResource.meta.versionId, ) updateChanges(entity, updatedResource) } diff --git a/engine/src/main/java/com/google/android/fhir/impl/FhirEngineImpl.kt b/engine/src/main/java/com/google/android/fhir/impl/FhirEngineImpl.kt index 4645c149bc..0c0b37c1d5 100644 --- a/engine/src/main/java/com/google/android/fhir/impl/FhirEngineImpl.kt +++ b/engine/src/main/java/com/google/android/fhir/impl/FhirEngineImpl.kt @@ -28,11 +28,11 @@ import com.google.android.fhir.search.count import com.google.android.fhir.search.execute import com.google.android.fhir.sync.ConflictResolver import com.google.android.fhir.sync.Resolved -import com.google.android.fhir.sync.upload.DefaultResourceConsolidator import com.google.android.fhir.sync.upload.LocalChangeFetcherFactory -import com.google.android.fhir.sync.upload.LocalChangesFetchMode +import com.google.android.fhir.sync.upload.ResourceConsolidatorFactory import com.google.android.fhir.sync.upload.SyncUploadProgress import com.google.android.fhir.sync.upload.UploadRequestResult +import com.google.android.fhir.sync.upload.UploadStrategy import java.time.OffsetDateTime import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.firstOrNull @@ -132,11 +132,13 @@ internal class FhirEngineImpl(private val database: Database, private val contex .intersect(database.getAllLocalChanges().map { it.resourceId }.toSet()) override suspend fun syncUpload( - localChangesFetchMode: LocalChangesFetchMode, + uploadStrategy: UploadStrategy, upload: (suspend (List) -> Flow), ): Flow = flow { - val resourceConsolidator = DefaultResourceConsolidator(database) - val localChangeFetcher = LocalChangeFetcherFactory.byMode(localChangesFetchMode, database) + val resourceConsolidator = + ResourceConsolidatorFactory.byHttpVerb(uploadStrategy.requestGeneratorMode, database) + val localChangeFetcher = + LocalChangeFetcherFactory.byMode(uploadStrategy.localChangesFetchMode, database) emit( SyncUploadProgress( diff --git a/engine/src/main/java/com/google/android/fhir/sync/FhirSyncWorker.kt b/engine/src/main/java/com/google/android/fhir/sync/FhirSyncWorker.kt index c5c525b2d1..afb43458be 100644 --- a/engine/src/main/java/com/google/android/fhir/sync/FhirSyncWorker.kt +++ b/engine/src/main/java/com/google/android/fhir/sync/FhirSyncWorker.kt @@ -91,16 +91,18 @@ abstract class FhirSyncWorker(appContext: Context, workerParams: WorkerParameter FhirSynchronizer( getFhirEngine(), UploadConfiguration( - Uploader( - dataSource = dataSource, - patchGenerator = - PatchGeneratorFactory.byMode( - getUploadStrategy().patchGeneratorMode, - FhirEngineProvider.getFhirDatabase(applicationContext), - ), - requestGenerator = - UploadRequestGeneratorFactory.byMode(getUploadStrategy().requestGeneratorMode), - ), + uploader = + Uploader( + dataSource = dataSource, + patchGenerator = + PatchGeneratorFactory.byMode( + getUploadStrategy().patchGeneratorMode, + FhirEngineProvider.getFhirDatabase(applicationContext), + ), + requestGenerator = + UploadRequestGeneratorFactory.byMode(getUploadStrategy().requestGeneratorMode), + ), + uploadStrategy = getUploadStrategy(), ), DownloadConfiguration( DownloaderImpl(dataSource, getDownloadWorkManager()), diff --git a/engine/src/main/java/com/google/android/fhir/sync/FhirSynchronizer.kt b/engine/src/main/java/com/google/android/fhir/sync/FhirSynchronizer.kt index 6f5232e311..10ee79f4e6 100644 --- a/engine/src/main/java/com/google/android/fhir/sync/FhirSynchronizer.kt +++ b/engine/src/main/java/com/google/android/fhir/sync/FhirSynchronizer.kt @@ -19,7 +19,7 @@ package com.google.android.fhir.sync import com.google.android.fhir.FhirEngine import com.google.android.fhir.sync.download.DownloadState import com.google.android.fhir.sync.download.Downloader -import com.google.android.fhir.sync.upload.LocalChangesFetchMode +import com.google.android.fhir.sync.upload.UploadStrategy import com.google.android.fhir.sync.upload.Uploader import java.time.OffsetDateTime import kotlinx.coroutines.flow.MutableSharedFlow @@ -46,6 +46,7 @@ data class ResourceSyncException(val resourceType: ResourceType, val exception: internal data class UploadConfiguration( val uploader: Uploader, + val uploadStrategy: UploadStrategy, ) internal class DownloadConfiguration( @@ -131,18 +132,18 @@ internal class FhirSynchronizer( private suspend fun upload(): SyncResult { val exceptions = mutableListOf() - val localChangesFetchMode = LocalChangesFetchMode.AllChanges - fhirEngine.syncUpload(localChangesFetchMode, uploadConfiguration.uploader::upload).collect { - progress -> - progress.uploadError?.let { exceptions.add(it) } - ?: setSyncState( - SyncJobStatus.InProgress( - SyncOperation.UPLOAD, - progress.initialTotal, - progress.initialTotal - progress.remaining, - ), - ) - } + fhirEngine + .syncUpload(uploadConfiguration.uploadStrategy, uploadConfiguration.uploader::upload) + .collect { progress -> + progress.uploadError?.let { exceptions.add(it) } + ?: setSyncState( + SyncJobStatus.InProgress( + SyncOperation.UPLOAD, + progress.initialTotal, + progress.initialTotal - progress.remaining, + ), + ) + } return if (exceptions.isEmpty()) { SyncResult.Success() diff --git a/engine/src/main/java/com/google/android/fhir/sync/upload/ResourceConsolidator.kt b/engine/src/main/java/com/google/android/fhir/sync/upload/ResourceConsolidator.kt index 051b2c3257..ea8870b5f5 100644 --- a/engine/src/main/java/com/google/android/fhir/sync/upload/ResourceConsolidator.kt +++ b/engine/src/main/java/com/google/android/fhir/sync/upload/ResourceConsolidator.kt @@ -18,9 +18,12 @@ package com.google.android.fhir.sync.upload import com.google.android.fhir.LocalChangeToken import com.google.android.fhir.db.Database +import com.google.android.fhir.sync.upload.request.UploadRequestGeneratorMode import org.hl7.fhir.r4.model.Bundle import org.hl7.fhir.r4.model.DomainResource +import org.hl7.fhir.r4.model.Resource import org.hl7.fhir.r4.model.ResourceType +import org.hl7.fhir.r4.model.codesystems.HttpVerb /** * Represents a mechanism to consolidate resources after they are uploaded. @@ -88,33 +91,101 @@ internal class DefaultResourceConsolidator(private val database: Database) : Res ) } } +} - /** - * FHIR uses weak ETag that look something like W/"MTY4NDMyODE2OTg3NDUyNTAwMA", so we need to - * extract version from it. See https://hl7.org/fhir/http.html#Http-Headers. - */ - private fun getVersionFromETag(eTag: String) = - // The server should always return a weak etag that starts with W, but if it server returns a - // strong tag, we store it as-is. The http-headers for conditional upload like if-match will - // always add value as a weak tag. - if (eTag.startsWith("W/")) { - eTag.split("\"")[1] - } else { - eTag +internal class HttpPostResourceConsolidator(private val database: Database) : ResourceConsolidator { + override suspend fun consolidate(uploadRequestResult: UploadRequestResult) = + when (uploadRequestResult) { + is UploadRequestResult.Success -> { + database.deleteUpdates( + LocalChangeToken( + uploadRequestResult.successfulUploadResponseMappings.flatMap { + it.localChanges.flatMap { localChange -> localChange.token.ids } + }, + ), + ) + uploadRequestResult.successfulUploadResponseMappings.forEach { + when (it) { + is BundleComponentUploadResponseMapping -> { + // TODO https://github.com/google/android-fhir/issues/2499 + throw NotImplementedError() + } + is ResourceUploadResponseMapping -> { + val preSyncResourceId = it.localChanges.firstOrNull()?.resourceId + preSyncResourceId?.let { preSyncResourceId -> + updateResourcePostSync(preSyncResourceId, it.output) + } + } + } + } + } + is UploadRequestResult.Failure -> { + /* For now, do nothing (we do not delete the local changes from the database as they were + not uploaded successfully. In the future, add consolidation required if upload fails. + */ + } + } + + private suspend fun updateResourcePostSync( + preSyncResourceId: String, + postSyncResource: Resource, + ) { + if ( + postSyncResource.hasMeta() && + postSyncResource.meta.hasVersionId() && + postSyncResource.meta.hasLastUpdated() + ) { + database.updateResourceAndReferences( + preSyncResourceId, + postSyncResource, + ) } + } +} - /** - * May return a Pair of versionId and resource type extracted from the - * [Bundle.BundleEntryResponseComponent.location]. - * - * [Bundle.BundleEntryResponseComponent.location] may be: - * 1. absolute path: `///_history/` - * 2. relative path: `//_history/` - */ - private val Bundle.BundleEntryResponseComponent.resourceIdAndType: Pair? - get() = - location - ?.split("/") - ?.takeIf { it.size > 3 } - ?.let { it[it.size - 3] to ResourceType.fromCode(it[it.size - 4]) } +/** + * FHIR uses weak ETag that look something like W/"MTY4NDMyODE2OTg3NDUyNTAwMA", so we need to + * extract version from it. See https://hl7.org/fhir/http.html#Http-Headers. + */ +private fun getVersionFromETag(eTag: String) = + // The server should always return a weak etag that starts with W, but if it server returns a + // strong tag, we store it as-is. The http-headers for conditional upload like if-match will + // always add value as a weak tag. + if (eTag.startsWith("W/")) { + eTag.split("\"")[1] + } else { + eTag + } + +/** + * May return a Pair of versionId and resource type extracted from the + * [Bundle.BundleEntryResponseComponent.location]. + * + * [Bundle.BundleEntryResponseComponent.location] may be: + * 1. absolute path: `///_history/` + * 2. relative path: `//_history/` + */ +private val Bundle.BundleEntryResponseComponent.resourceIdAndType: Pair? + get() = + location + ?.split("/") + ?.takeIf { it.size > 3 } + ?.let { it[it.size - 3] to ResourceType.fromCode(it[it.size - 4]) } + +internal object ResourceConsolidatorFactory { + fun byHttpVerb( + uploadRequestMode: UploadRequestGeneratorMode, + database: Database, + ): ResourceConsolidator { + val httpVerbToUse = + when (uploadRequestMode) { + is UploadRequestGeneratorMode.UrlRequest -> uploadRequestMode.httpVerbToUseForCreate + is UploadRequestGeneratorMode.BundleRequest -> uploadRequestMode.httpVerbToUseForCreate + } + return if (httpVerbToUse.toString() == HttpVerb.POST.toCode()) { + HttpPostResourceConsolidator(database) + } else { + DefaultResourceConsolidator(database) + } + } } diff --git a/engine/src/main/java/com/google/android/fhir/sync/upload/UploadStrategy.kt b/engine/src/main/java/com/google/android/fhir/sync/upload/UploadStrategy.kt index f6bc702d79..a926aac516 100644 --- a/engine/src/main/java/com/google/android/fhir/sync/upload/UploadStrategy.kt +++ b/engine/src/main/java/com/google/android/fhir/sync/upload/UploadStrategy.kt @@ -62,13 +62,24 @@ private constructor( * bundled PUT request. This strategy is efficient and minimizes the number of requests sent to * the server, but does not maintain individual change history. */ - object AllChangesSquashedBundlePut : + data object AllChangesSquashedBundlePut : UploadStrategy( LocalChangesFetchMode.AllChanges, PatchGeneratorMode.PerResource, UploadRequestGeneratorMode.BundleRequest(Bundle.HTTPVerb.PUT, Bundle.HTTPVerb.PATCH), ) + /** + * Fetches all changes for a single resource, generates a patch for that resource, and creates a + * single POST request with the patch. + */ + data object SingleResourcePost : + UploadStrategy( + LocalChangesFetchMode.PerResource, + PatchGeneratorMode.PerResource, + UploadRequestGeneratorMode.UrlRequest(HttpVerb.POST, HttpVerb.PATCH), + ) + /* * All the [UploadStrategy]s below this line are still in progress and not available as of now. As * and when an [UploadStrategy] is implemented, it should be moved above this comment section and @@ -119,17 +130,6 @@ private constructor( UploadRequestGeneratorMode.UrlRequest(HttpVerb.PUT, HttpVerb.PATCH), ) - /** - * Not yet implemented - Fetches all changes for a single resource, generates a patch for that - * resource, and creates a single POST request with the patch. - */ - private object SingleResourcePost : - UploadStrategy( - LocalChangesFetchMode.PerResource, - PatchGeneratorMode.PerResource, - UploadRequestGeneratorMode.UrlRequest(HttpVerb.POST, HttpVerb.PATCH), - ) - /** * Not yet implemented - Fetches all local changes, generates a patch for each individual change, * and creates a single bundle POST request containing all the patches. diff --git a/engine/src/main/java/com/google/android/fhir/testing/Utilities.kt b/engine/src/main/java/com/google/android/fhir/testing/Utilities.kt index 07c764241a..e6c0441158 100644 --- a/engine/src/main/java/com/google/android/fhir/testing/Utilities.kt +++ b/engine/src/main/java/com/google/android/fhir/testing/Utilities.kt @@ -31,9 +31,9 @@ import com.google.android.fhir.sync.DownloadWorkManager import com.google.android.fhir.sync.download.BundleDownloadRequest import com.google.android.fhir.sync.download.DownloadRequest import com.google.android.fhir.sync.download.UrlDownloadRequest -import com.google.android.fhir.sync.upload.LocalChangesFetchMode import com.google.android.fhir.sync.upload.SyncUploadProgress import com.google.android.fhir.sync.upload.UploadRequestResult +import com.google.android.fhir.sync.upload.UploadStrategy import com.google.android.fhir.sync.upload.request.BundleUploadRequest import com.google.android.fhir.sync.upload.request.UploadRequest import com.google.android.fhir.sync.upload.request.UrlUploadRequest @@ -157,7 +157,7 @@ object TestFhirEngineImpl : FhirEngine { } override suspend fun syncUpload( - localChangesFetchMode: LocalChangesFetchMode, + uploadStrategy: UploadStrategy, upload: suspend (List) -> Flow, ): Flow = flow { emit(SyncUploadProgress(1, 1)) diff --git a/engine/src/test/java/com/google/android/fhir/impl/FhirEngineImplTest.kt b/engine/src/test/java/com/google/android/fhir/impl/FhirEngineImplTest.kt index 21d440a1ba..48be1a491b 100644 --- a/engine/src/test/java/com/google/android/fhir/impl/FhirEngineImplTest.kt +++ b/engine/src/test/java/com/google/android/fhir/impl/FhirEngineImplTest.kt @@ -30,10 +30,10 @@ import com.google.android.fhir.search.search import com.google.android.fhir.sync.AcceptLocalConflictResolver import com.google.android.fhir.sync.AcceptRemoteConflictResolver import com.google.android.fhir.sync.ResourceSyncException -import com.google.android.fhir.sync.upload.LocalChangesFetchMode import com.google.android.fhir.sync.upload.ResourceUploadResponseMapping import com.google.android.fhir.sync.upload.SyncUploadProgress import com.google.android.fhir.sync.upload.UploadRequestResult +import com.google.android.fhir.sync.upload.UploadStrategy import com.google.android.fhir.testing.assertResourceEquals import com.google.android.fhir.testing.assertResourceNotEquals import com.google.android.fhir.testing.readFromFile @@ -323,7 +323,7 @@ class FhirEngineImplTest { val emittedProgress = mutableListOf() fhirEngine - .syncUpload(LocalChangesFetchMode.AllChanges) { + .syncUpload(UploadStrategy.AllChangesSquashedBundlePut) { localChanges.addAll(it) flowOf( UploadRequestResult.Success( @@ -356,7 +356,7 @@ class FhirEngineImplTest { val emittedProgress = mutableListOf() val uploadError = ResourceSyncException(ResourceType.Patient, FHIRException("Did not work")) fhirEngine - .syncUpload(LocalChangesFetchMode.AllChanges) { + .syncUpload(UploadStrategy.AllChangesSquashedBundlePut) { flowOf( UploadRequestResult.Failure( it, @@ -763,6 +763,26 @@ class FhirEngineImplTest { .inOrder() } + @Test + fun `test local changes are consumed when using POST upload strategy`() = runBlocking { + assertThat(services.database.getLocalChangesCount()).isEqualTo(1) + fhirEngine + .syncUpload(UploadStrategy.SingleResourcePost) { + flowOf( + UploadRequestResult.Success( + listOf( + ResourceUploadResponseMapping( + it, + TEST_PATIENT_1, + ), + ), + ), + ) + } + .collect {} + assertThat(services.database.getLocalChangesCount()).isEqualTo(0) + } + companion object { private const val TEST_PATIENT_1_ID = "test_patient_1" private var TEST_PATIENT_1 = diff --git a/engine/src/test/java/com/google/android/fhir/sync/FhirSynchronizerTest.kt b/engine/src/test/java/com/google/android/fhir/sync/FhirSynchronizerTest.kt index 299c3e4342..22c6fb6709 100644 --- a/engine/src/test/java/com/google/android/fhir/sync/FhirSynchronizerTest.kt +++ b/engine/src/test/java/com/google/android/fhir/sync/FhirSynchronizerTest.kt @@ -19,6 +19,7 @@ package com.google.android.fhir.sync import com.google.android.fhir.sync.download.DownloadState import com.google.android.fhir.sync.download.Downloader import com.google.android.fhir.sync.upload.UploadRequestResult +import com.google.android.fhir.sync.upload.UploadStrategy import com.google.android.fhir.sync.upload.Uploader import com.google.android.fhir.testing.TestFhirEngineImpl import com.google.common.truth.Truth.assertThat @@ -59,7 +60,7 @@ class FhirSynchronizerTest { fhirSynchronizer = FhirSynchronizer( TestFhirEngineImpl, - UploadConfiguration(uploader), + UploadConfiguration(uploader, UploadStrategy.AllChangesSquashedBundlePut), DownloadConfiguration(downloader, conflictResolver), fhirDataStore, ) @@ -158,7 +159,7 @@ class FhirSynchronizerTest { val fhirSynchronizerWithDelayInDownload = FhirSynchronizer( TestFhirEngineImpl, - UploadConfiguration(uploader), + UploadConfiguration(uploader, UploadStrategy.AllChangesSquashedBundlePut), DownloadConfiguration( object : Downloader { override suspend fun download(): Flow { diff --git a/engine/src/test/java/com/google/android/fhir/sync/upload/ResourceConsolidatorFactoryTest.kt b/engine/src/test/java/com/google/android/fhir/sync/upload/ResourceConsolidatorFactoryTest.kt new file mode 100644 index 0000000000..10c1fee372 --- /dev/null +++ b/engine/src/test/java/com/google/android/fhir/sync/upload/ResourceConsolidatorFactoryTest.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2024 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.sync.upload + +import androidx.test.core.app.ApplicationProvider +import com.google.android.fhir.FhirServices +import kotlin.test.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner + +@RunWith(RobolectricTestRunner::class) +class ResourceConsolidatorFactoryTest { + private val services = + FhirServices.builder(ApplicationProvider.getApplicationContext()).inMemory().build() + + @Test + fun `return HttpPostResourceConsolidator instance `() { + val httpPostResourceConsolidator = + ResourceConsolidatorFactory.byHttpVerb( + UploadStrategy.SingleResourcePost.requestGeneratorMode, + services.database, + ) + assertTrue(httpPostResourceConsolidator is HttpPostResourceConsolidator) + } + + @Test + fun `return DefaultResourceConsolidator instance `() { + val httpPostResourceConsolidator = + ResourceConsolidatorFactory.byHttpVerb( + UploadStrategy.AllChangesSquashedBundlePut.requestGeneratorMode, + services.database, + ) + assertTrue(httpPostResourceConsolidator is DefaultResourceConsolidator) + } +} From c6adeb424aae18d0a8db128bba52eeaea2a7270d Mon Sep 17 00:00:00 2001 From: Jing Tang Date: Fri, 31 May 2024 10:31:37 +0100 Subject: [PATCH 5/9] Remove unnecessary deps (#2558) --- buildSrc/src/main/kotlin/Dependencies.kt | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 6b511ac067..296b3b9290 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -48,7 +48,6 @@ object Dependencies { const val structuresDstu2Module = "ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2" const val structuresDstu3Module = "ca.uhn.hapi.fhir:hapi-fhir-structures-dstu3" const val structuresR4Module = "ca.uhn.hapi.fhir:hapi-fhir-structures-r4" - const val structuresR4bModule = "ca.uhn.hapi.fhir:hapi-fhir-structures-r4b" const val structuresR5Module = "ca.uhn.hapi.fhir:hapi-fhir-structures-r5" const val validationModule = "ca.uhn.hapi.fhir:hapi-fhir-validation" @@ -67,26 +66,11 @@ object Dependencies { const val guavaCachingModule = "ca.uhn.hapi.fhir:hapi-fhir-caching-guava" - const val fhirBase = "$fhirBaseModule:${Versions.hapiFhir}" - const val fhirClient = "$fhirClientModule:${Versions.hapiFhir}" - const val structuresDstu2 = "$structuresDstu2Module:${Versions.hapiFhir}" - const val structuresDstu3 = "$structuresDstu3Module:${Versions.hapiFhir}" const val structuresR4 = "$structuresR4Module:${Versions.hapiFhir}" - const val structuresR4b = "$structuresR4bModule:${Versions.hapiFhir}" - const val structuresR5 = "$structuresR5Module:${Versions.hapiFhir}" const val validation = "$validationModule:${Versions.hapiFhir}" - const val validationDstu3 = "$validationDstu3Module:${Versions.hapiFhir}" const val validationR4 = "$validationR4Module:${Versions.hapiFhir}" - const val validationR5 = "$validationR5Module:${Versions.hapiFhir}" - - const val fhirCoreDstu2 = "$fhirCoreDstu2Module:${Versions.hapiFhirCore}" - const val fhirCoreDstu2016 = "$fhirCoreDstu2016Module:${Versions.hapiFhirCore}" - const val fhirCoreDstu3 = "$fhirCoreDstu3Module:${Versions.hapiFhirCore}" - const val fhirCoreR4 = "$fhirCoreR4Module:${Versions.hapiFhirCore}" - const val fhirCoreR4b = "$fhirCoreR4bModule:${Versions.hapiFhirCore}" - const val fhirCoreR5 = "$fhirCoreR5Module:${Versions.hapiFhirCore}" - const val fhirCoreUtils = "$fhirCoreUtilsModule:${Versions.hapiFhirCore}" + const val fhirCoreConvertors = "$fhirCoreConvertorsModule:${Versions.hapiFhirCore}" const val guavaCaching = "$guavaCachingModule:${Versions.hapiFhir}" @@ -330,7 +314,7 @@ object Dependencies { } fun hapiFhirConstraints(): Map Unit> { - return mutableMapOf Unit>( + return mutableMapOf( guavaModule to { version { strictly(Versions.guava) } }, HapiFhir.fhirBaseModule to { version { strictly(Versions.hapiFhir) } }, HapiFhir.fhirClientModule to { version { strictly(Versions.hapiFhir) } }, From 5efb955619cc1f0ca54e0ce4bee9b7c69360d67b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 May 2024 11:40:38 +0100 Subject: [PATCH 6/9] --- (#2548) updated-dependencies: - dependency-name: requests dependency-type: indirect dependency-group: pip ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Pipfile.lock | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index f82b17ef3b..4095bfa7a0 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -547,11 +547,12 @@ }, "requests": { "hashes": [ - "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f", - "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1" + "sha256:f2c3881dddb70d056c5bd7600a4fae312b2a300e39be6a118d30b90bd27262b5", + "sha256:fa5490319474c82ef1d2c9bc459d3652e3ae4ef4c4ebdd18a21145a47ca4b6b8" ], - "markers": "python_version >= '3.7'", - "version": "==2.31.0" + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==2.32.0" }, "six": { "hashes": [ From 9f4fe88d1eeed9f8bc335050be7596471ea69fec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 31 May 2024 16:59:05 +0100 Subject: [PATCH 7/9] Bump actions/configure-pages from 4 to 5 (#2504) Bumps [actions/configure-pages](https://github.com/actions/configure-pages) from 4 to 5. - [Release notes](https://github.com/actions/configure-pages/releases) - [Commits](https://github.com/actions/configure-pages/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/configure-pages dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 01406d99ec..f87a25b257 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -118,7 +118,7 @@ jobs: - name: Setup GitHub Pages if: ${{ github.event_name == 'push' }} - uses: actions/configure-pages@v4 + uses: actions/configure-pages@v5 - name: Upload site/ directory as GitHub Pages artifact if: ${{ github.event_name == 'push' }} From 0611581b0928f58b4a9e6fc31c9152b264d2778b Mon Sep 17 00:00:00 2001 From: williamito Date: Mon, 3 Jun 2024 03:39:46 -0700 Subject: [PATCH 8/9] Mark many things as internal (#2494) * Mark ContentTypes and MediaTypes as internal * Mark more things internal, refactor demo to not use util function --------- Co-authored-by: santosh-pingle <86107848+santosh-pingle@users.noreply.github.com> --- .../fhir/demo/PatientDetailsViewModel.kt | 12 +++++++-- .../com/google/android/fhir/ContentTypes.kt | 6 ++--- .../com/google/android/fhir/DateProvider.kt | 4 +-- .../google/android/fhir/FhirEngineProvider.kt | 12 ++++----- .../com/google/android/fhir/LocalChange.kt | 2 +- .../main/java/com/google/android/fhir/Util.kt | 10 ++++---- .../com/google/android/fhir/db/Database.kt | 4 +-- .../android/fhir/db/impl/DatabaseImpl.kt | 2 +- .../android/fhir/db/impl/ResourceDatabase.kt | 16 ++++++------ .../fhir/db/impl/SQLCipherSupportHelper.kt | 4 +-- .../fhir/index/DualHapiWorkerContext.kt | 4 +-- .../android/fhir/index/ResourceIndexer.kt | 8 ++++-- .../fhir/index/entities/PositionIndex.kt | 4 +-- .../fhir/search/query/XFhirQueryTranslator.kt | 4 +-- .../fhir/sync/remote/FhirConverterFactory.kt | 2 +- .../android/fhir/sync/upload/patch/Patch.kt | 4 +-- .../request/BundleEntryComponentGenerator.kt | 4 +-- .../google/android/fhir/testing/Utilities.kt | 25 ++++++++++--------- .../android/fhir/sync/FhirSyncWorkerTest.kt | 2 +- .../request/RequestGeneratorTestUtils.kt | 4 +-- 20 files changed, 73 insertions(+), 60 deletions(-) diff --git a/demo/src/main/java/com/google/android/fhir/demo/PatientDetailsViewModel.kt b/demo/src/main/java/com/google/android/fhir/demo/PatientDetailsViewModel.kt index 14336bba7f..014177a327 100644 --- a/demo/src/main/java/com/google/android/fhir/demo/PatientDetailsViewModel.kt +++ b/demo/src/main/java/com/google/android/fhir/demo/PatientDetailsViewModel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,7 +26,6 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope import com.google.android.fhir.FhirEngine -import com.google.android.fhir.logicalId import com.google.android.fhir.search.revInclude import com.google.android.fhir.search.search import java.text.SimpleDateFormat @@ -379,3 +378,12 @@ data class RiskAssessmentItem( var lastContacted: String, var patientCardColor: Int, ) + +/** + * The logical (unqualified) part of the ID. For example, if the ID is + * "http://example.com/fhir/Patient/123/_history/456", then this value would be "123". + */ +private val Resource.logicalId: String + get() { + return this.idElement?.idPart.orEmpty() + } diff --git a/engine/src/main/java/com/google/android/fhir/ContentTypes.kt b/engine/src/main/java/com/google/android/fhir/ContentTypes.kt index eaad96cf1b..6a491d04c0 100644 --- a/engine/src/main/java/com/google/android/fhir/ContentTypes.kt +++ b/engine/src/main/java/com/google/android/fhir/ContentTypes.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Google LLC + * Copyright 2021-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,11 +18,11 @@ package com.google.android.fhir import okhttp3.MediaType.Companion.toMediaType -object ContentTypes { +internal object ContentTypes { const val APPLICATION_JSON_PATCH = "application/json-patch+json" const val APPLICATION_FHIR_JSON = "application/fhir+json" } -object MediaTypes { +internal object MediaTypes { val MEDIA_TYPE_FHIR_JSON = ContentTypes.APPLICATION_FHIR_JSON.toMediaType() } diff --git a/engine/src/main/java/com/google/android/fhir/DateProvider.kt b/engine/src/main/java/com/google/android/fhir/DateProvider.kt index 9d98095f95..b62ea0d7d2 100644 --- a/engine/src/main/java/com/google/android/fhir/DateProvider.kt +++ b/engine/src/main/java/com/google/android/fhir/DateProvider.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021-2023 Google LLC + * Copyright 2021-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ import java.time.Instant import java.time.ZoneId /** The DateProvider Instance [FhirEngine] uses for date/time related operations. */ -object DateProvider { +internal object DateProvider { lateinit var clock: Clock private var fixed = false // TODO possibly provide more customization options diff --git a/engine/src/main/java/com/google/android/fhir/FhirEngineProvider.kt b/engine/src/main/java/com/google/android/fhir/FhirEngineProvider.kt index 076c0e27ed..ae3ab614fe 100644 --- a/engine/src/main/java/com/google/android/fhir/FhirEngineProvider.kt +++ b/engine/src/main/java/com/google/android/fhir/FhirEngineProvider.kt @@ -125,7 +125,7 @@ object FhirEngineProvider { * `enableEncryptionIfSupported` is true, the FHIR SDK will only enable database encryption on * supported devices. * - * WARNING: If database encryption is enabled, devices that are on API 22 (Android 5.1) or lower + * **WARNING:** If database encryption is enabled, devices that are on API 22 (Android 5.1) or lower * will have an unencrypted database. If those devices are later updated to API 23 or newer, they * will encounter an `IllegalStateException`. This is because the database was created without * encryption on the older API level, and enabling encryption in the new release will not @@ -143,11 +143,10 @@ object FhirEngineProvider { * engine with the Search API. These are in addition to the default * [search parameters](https://www.hl7.org/fhir/searchparameter-registry.html) defined in the FHIR * specification. Custom search parameters must be unique and not change existing or default - * search parameters. - * - * Note: The engine does not automatically reindex resources after new custom search parameters are - * added. You must manually reindex resources by updating them. Any new CRUD operations on a - * resource after adding new search parameters will automatically trigger reindexing. + * search parameters.

**Note:** The engine does not automatically reindex resources after new + * custom search parameters are added. You must manually reindex resources by updating them. Any + * new CRUD operations on a resource after adding new search parameters will automatically trigger + * reindexing. */ data class FhirEngineConfiguration( val enableEncryptionIfSupported: Boolean = false, @@ -157,6 +156,7 @@ data class FhirEngineConfiguration( val customSearchParameters: List? = null, ) +/** How database errors should be handled. */ enum class DatabaseErrorStrategy { /** * If unspecified, all database errors will be propagated to the call site. The caller shall diff --git a/engine/src/main/java/com/google/android/fhir/LocalChange.kt b/engine/src/main/java/com/google/android/fhir/LocalChange.kt index c790e95862..e1e7d7c8a0 100644 --- a/engine/src/main/java/com/google/android/fhir/LocalChange.kt +++ b/engine/src/main/java/com/google/android/fhir/LocalChange.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 Google LLC + * Copyright 2022-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/engine/src/main/java/com/google/android/fhir/Util.kt b/engine/src/main/java/com/google/android/fhir/Util.kt index 5c9dc0f69f..5ad65a52e9 100644 --- a/engine/src/main/java/com/google/android/fhir/Util.kt +++ b/engine/src/main/java/com/google/android/fhir/Util.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 Google LLC + * Copyright 2022-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,7 +50,7 @@ internal fun isValidDateOnly(date: String) = * The logical (unqualified) part of the ID. For example, if the ID is * "http://example.com/fhir/Patient/123/_history/456", then this value would be "123". */ -val Resource.logicalId: String +internal val Resource.logicalId: String get() { return this.idElement?.idPart.orEmpty() } @@ -62,14 +62,14 @@ val Resource.logicalId: String * operation success/failure. TODO: pass along the HTTP result (or any other signal) to determine * the outcome of an instance level RESTful operation. */ -fun Resource.isUploadSuccess(): Boolean { +internal fun Resource.isUploadSuccess(): Boolean { if (!this.resourceType.equals(ResourceType.OperationOutcome)) return false val outcome: OperationOutcome = this as OperationOutcome return outcome.issue.isNotEmpty() && outcome.issue.all { it.severity.equals(OperationOutcome.IssueSeverity.INFORMATION) } } -class OffsetDateTimeTypeAdapter : TypeAdapter() { +internal class OffsetDateTimeTypeAdapter : TypeAdapter() { override fun write(out: JsonWriter, value: OffsetDateTime) { out.value(DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(value)) } @@ -78,7 +78,7 @@ class OffsetDateTimeTypeAdapter : TypeAdapter() { } /** Url for the UCUM system of measures. */ -const val ucumUrl = "http://unitsofmeasure.org" +internal const val ucumUrl = "http://unitsofmeasure.org" internal fun percentOf(value: Number, total: Number) = if (total == 0) 0.0 else value.toDouble() / total.toDouble() diff --git a/engine/src/main/java/com/google/android/fhir/db/Database.kt b/engine/src/main/java/com/google/android/fhir/db/Database.kt index 0107f67d2f..251bf21b6c 100644 --- a/engine/src/main/java/com/google/android/fhir/db/Database.kt +++ b/engine/src/main/java/com/google/android/fhir/db/Database.kt @@ -196,12 +196,12 @@ internal interface Database { ): List } -data class ResourceWithUUID( +internal data class ResourceWithUUID( val uuid: UUID, val resource: R, ) -data class LocalChangeResourceReference( +internal data class LocalChangeResourceReference( val localChangeId: Long, val resourceReferenceValue: String, val resourceReferencePath: String?, diff --git a/engine/src/main/java/com/google/android/fhir/db/impl/DatabaseImpl.kt b/engine/src/main/java/com/google/android/fhir/db/impl/DatabaseImpl.kt index b156b46728..2e14ea6b1d 100644 --- a/engine/src/main/java/com/google/android/fhir/db/impl/DatabaseImpl.kt +++ b/engine/src/main/java/com/google/android/fhir/db/impl/DatabaseImpl.kt @@ -444,7 +444,7 @@ internal class DatabaseImpl( } } -data class DatabaseConfig( +internal data class DatabaseConfig( val inMemory: Boolean, val enableEncryption: Boolean, val databaseErrorStrategy: DatabaseErrorStrategy, diff --git a/engine/src/main/java/com/google/android/fhir/db/impl/ResourceDatabase.kt b/engine/src/main/java/com/google/android/fhir/db/impl/ResourceDatabase.kt index 3502ab0b8e..158bb4b146 100644 --- a/engine/src/main/java/com/google/android/fhir/db/impl/ResourceDatabase.kt +++ b/engine/src/main/java/com/google/android/fhir/db/impl/ResourceDatabase.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -64,14 +64,14 @@ internal abstract class ResourceDatabase : RoomDatabase() { abstract fun localChangeDao(): LocalChangeDao } -val MIGRATION_1_2 = +internal val MIGRATION_1_2 = object : Migration(1, 2) { override fun migrate(database: SupportSQLiteDatabase) { database.execSQL("DROP table if exists SyncedResourceEntity") } } -val MIGRATION_2_3 = +internal val MIGRATION_2_3 = object : Migration(2, 3) { override fun migrate(database: SupportSQLiteDatabase) { database.execSQL( @@ -80,7 +80,7 @@ val MIGRATION_2_3 = } } -val MIGRATION_3_4 = +internal val MIGRATION_3_4 = object : Migration(3, 4) { override fun migrate(database: SupportSQLiteDatabase) { database.execSQL( @@ -105,7 +105,7 @@ val MIGRATION_3_4 = } } -val MIGRATION_4_5 = +internal val MIGRATION_4_5 = object : Migration(4, 5) { override fun migrate(database: SupportSQLiteDatabase) { database.execSQL( @@ -115,7 +115,7 @@ val MIGRATION_4_5 = } /** Changes column type of [LocalChangeEntity.timestamp] from [String] to [java.time.Instant]. */ -val MIGRATION_5_6 = +internal val MIGRATION_5_6 = object : Migration(5, 6) { override fun migrate(database: SupportSQLiteDatabase) { database.execSQL( @@ -133,7 +133,7 @@ val MIGRATION_5_6 = } /** Add column resourceUuid in [LocalChangeEntity] */ -val MIGRATION_6_7 = +internal val MIGRATION_6_7 = object : Migration(6, 7) { override fun migrate(database: SupportSQLiteDatabase) { database.execSQL( @@ -155,7 +155,7 @@ val MIGRATION_6_7 = } /** Create [LocalChangeResourceReferenceEntity] */ -val MIGRATION_7_8 = +internal val MIGRATION_7_8 = object : Migration(7, 8) { override fun migrate(database: SupportSQLiteDatabase) { database.execSQL( diff --git a/engine/src/main/java/com/google/android/fhir/db/impl/SQLCipherSupportHelper.kt b/engine/src/main/java/com/google/android/fhir/db/impl/SQLCipherSupportHelper.kt index eaf8393d51..f761656e11 100644 --- a/engine/src/main/java/com/google/android/fhir/db/impl/SQLCipherSupportHelper.kt +++ b/engine/src/main/java/com/google/android/fhir/db/impl/SQLCipherSupportHelper.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ import net.sqlcipher.database.SQLiteOpenHelper import timber.log.Timber /** A [SupportSQLiteOpenHelper] which initializes a [SQLiteDatabase] with a passphrase. */ -class SQLCipherSupportHelper( +internal class SQLCipherSupportHelper( private val configuration: SupportSQLiteOpenHelper.Configuration, hook: SQLiteDatabaseHook? = null, private val databaseErrorStrategy: DatabaseErrorStrategy, diff --git a/engine/src/main/java/com/google/android/fhir/index/DualHapiWorkerContext.kt b/engine/src/main/java/com/google/android/fhir/index/DualHapiWorkerContext.kt index bfd12c5422..02306848ce 100644 --- a/engine/src/main/java/com/google/android/fhir/index/DualHapiWorkerContext.kt +++ b/engine/src/main/java/com/google/android/fhir/index/DualHapiWorkerContext.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ import org.hl7.fhir.r4.model.Resource * * TODO: Ideally we update the upstream's HapiWorkerContext to support ucumServices. */ -class DualHapiWorkerContext : SimpleWorkerContext() { +internal class DualHapiWorkerContext : SimpleWorkerContext() { val hapi = HapiWorkerContext( FhirContext.forR4Cached(), diff --git a/engine/src/main/java/com/google/android/fhir/index/ResourceIndexer.kt b/engine/src/main/java/com/google/android/fhir/index/ResourceIndexer.kt index b1c3f81468..8e07a8b5ae 100644 --- a/engine/src/main/java/com/google/android/fhir/index/ResourceIndexer.kt +++ b/engine/src/main/java/com/google/android/fhir/index/ResourceIndexer.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -389,4 +389,8 @@ internal class ResourceIndexer( } } -data class SearchParamDefinition(val name: String, val type: SearchParamType, val path: String) +internal data class SearchParamDefinition( + val name: String, + val type: SearchParamType, + val path: String, +) diff --git a/engine/src/main/java/com/google/android/fhir/index/entities/PositionIndex.kt b/engine/src/main/java/com/google/android/fhir/index/entities/PositionIndex.kt index d052326ef5..f6bcfcc161 100644 --- a/engine/src/main/java/com/google/android/fhir/index/entities/PositionIndex.kt +++ b/engine/src/main/java/com/google/android/fhir/index/entities/PositionIndex.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 Google LLC + * Copyright 2021-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,4 +21,4 @@ package com.google.android.fhir.index.entities * * See https://www.hl7.org/fhir/search.html#special. */ -data class PositionIndex(val latitude: Double, val longitude: Double) +internal data class PositionIndex(val latitude: Double, val longitude: Double) diff --git a/engine/src/main/java/com/google/android/fhir/search/query/XFhirQueryTranslator.kt b/engine/src/main/java/com/google/android/fhir/search/query/XFhirQueryTranslator.kt index ce158d32d9..9681728c0a 100644 --- a/engine/src/main/java/com/google/android/fhir/search/query/XFhirQueryTranslator.kt +++ b/engine/src/main/java/com/google/android/fhir/search/query/XFhirQueryTranslator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 Google LLC + * Copyright 2022-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,7 +44,7 @@ import org.hl7.fhir.r4.model.ResourceType * http://build.fhir.org/ig/HL7/sdc/expressions.html#x-fhir-query-enhancements and * http://hl7.org/fhir/R4/search.html */ -object XFhirQueryTranslator { +internal object XFhirQueryTranslator { private const val XFHIR_QUERY_SORT_PARAM = "_sort" private const val XFHIR_QUERY_COUNT_PARAM = "_count" diff --git a/engine/src/main/java/com/google/android/fhir/sync/remote/FhirConverterFactory.kt b/engine/src/main/java/com/google/android/fhir/sync/remote/FhirConverterFactory.kt index fc2fab0c70..bd8fbe63f3 100644 --- a/engine/src/main/java/com/google/android/fhir/sync/remote/FhirConverterFactory.kt +++ b/engine/src/main/java/com/google/android/fhir/sync/remote/FhirConverterFactory.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/engine/src/main/java/com/google/android/fhir/sync/upload/patch/Patch.kt b/engine/src/main/java/com/google/android/fhir/sync/upload/patch/Patch.kt index bf3b6fac68..103aaac1bf 100644 --- a/engine/src/main/java/com/google/android/fhir/sync/upload/patch/Patch.kt +++ b/engine/src/main/java/com/google/android/fhir/sync/upload/patch/Patch.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ import java.time.Instant import org.hl7.fhir.r4.model.Resource /** Data class for squashed local changes for resource */ -data class Patch( +internal data class Patch( /** The [ResourceType] */ val resourceType: String, /** The resource id [Resource.id] */ diff --git a/engine/src/main/java/com/google/android/fhir/sync/upload/request/BundleEntryComponentGenerator.kt b/engine/src/main/java/com/google/android/fhir/sync/upload/request/BundleEntryComponentGenerator.kt index 372ed59c93..329a2965a9 100644 --- a/engine/src/main/java/com/google/android/fhir/sync/upload/request/BundleEntryComponentGenerator.kt +++ b/engine/src/main/java/com/google/android/fhir/sync/upload/request/BundleEntryComponentGenerator.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ import org.hl7.fhir.r4.model.UriType * [LocalChangeEntity]. See [https://www.hl7.org/fhir/http.html#transaction] for more info regarding * the supported [Bundle.HTTPVerb]. */ -abstract class BundleEntryComponentGenerator( +internal abstract class BundleEntryComponentGenerator( private val httpVerb: Bundle.HTTPVerb, private val useETagForUpload: Boolean, ) { diff --git a/engine/src/main/java/com/google/android/fhir/testing/Utilities.kt b/engine/src/main/java/com/google/android/fhir/testing/Utilities.kt index e6c0441158..c99e17be73 100644 --- a/engine/src/main/java/com/google/android/fhir/testing/Utilities.kt +++ b/engine/src/main/java/com/google/android/fhir/testing/Utilities.kt @@ -55,21 +55,21 @@ import org.hl7.fhir.r4.model.ResourceType import org.json.JSONArray import org.json.JSONObject -val jsonParser: IParser = FhirContext.forCached(FhirVersionEnum.R4).newJsonParser() +internal val jsonParser: IParser = FhirContext.forCached(FhirVersionEnum.R4).newJsonParser() /** Asserts that the `expected` and the `actual` FHIR resources are equal. */ -fun assertResourceEquals(expected: Resource?, actual: Resource?) { +internal fun assertResourceEquals(expected: Resource?, actual: Resource?) { assertThat(jsonParser.encodeResourceToString(actual)) .isEqualTo(jsonParser.encodeResourceToString(expected)) } /** Asserts that the `expected` and the `actual` FHIR resources are not equal. */ -fun assertResourceNotEquals(expected: Resource?, actual: Resource?) { +internal fun assertResourceNotEquals(expected: Resource?, actual: Resource?) { assertThat(jsonParser.encodeResourceToString(actual)) .isNotEqualTo(jsonParser.encodeResourceToString(expected)) } -fun assertJsonArrayEqualsIgnoringOrder(actual: JSONArray, expected: JSONArray) { +internal fun assertJsonArrayEqualsIgnoringOrder(actual: JSONArray, expected: JSONArray) { assertThat(actual.length()).isEqualTo(expected.length()) val actuals = mutableListOf() val expecteds = mutableListOf() @@ -83,7 +83,7 @@ fun assertJsonArrayEqualsIgnoringOrder(actual: JSONArray, expected: JSONArray) { } /** Reads a [Resource] from given file in the `sampledata` dir */ -fun readFromFile(clazz: Class, filename: String): R { +internal fun readFromFile(clazz: Class, filename: String): R { val resourceJson = readJsonFromFile(filename) return jsonParser.parseResource(clazz, resourceJson.toString()) as R } @@ -96,13 +96,13 @@ private fun readJsonFromFile(filename: String): JSONObject { } /** Reads a [JSONArray] from given file in the `sampledata` dir */ -fun readJsonArrayFromFile(filename: String): JSONArray { +internal fun readJsonArrayFromFile(filename: String): JSONArray { val inputStream = {}.javaClass.getResourceAsStream(filename) val content = inputStream!!.bufferedReader(Charsets.UTF_8).readText() return JSONArray(content) } -object TestDataSourceImpl : DataSource { +internal object TestDataSourceImpl : DataSource { override suspend fun download(downloadRequest: DownloadRequest) = when (downloadRequest) { @@ -120,7 +120,7 @@ object TestDataSourceImpl : DataSource { } } -open class TestDownloadManagerImpl( +internal open class TestDownloadManagerImpl( private val queries: List = listOf("Patient?address-city=NAIROBI"), ) : DownloadWorkManager { private val urls = LinkedList(queries) @@ -141,7 +141,7 @@ open class TestDownloadManagerImpl( } } -object TestFhirEngineImpl : FhirEngine { +internal object TestFhirEngineImpl : FhirEngine { override suspend fun create(vararg resource: Resource) = emptyList() override suspend fun update(vararg resource: Resource) {} @@ -204,7 +204,7 @@ object TestFhirEngineImpl : FhirEngine { override suspend fun purge(type: ResourceType, ids: Set, forcePurge: Boolean) {} } -object TestFailingDatasource : DataSource { +internal object TestFailingDatasource : DataSource { override suspend fun download(downloadRequest: DownloadRequest) = when (downloadRequest) { @@ -223,7 +223,8 @@ object TestFailingDatasource : DataSource { } } -class BundleDataSource(val onPostBundle: suspend (BundleUploadRequest) -> Resource) : DataSource { +internal class BundleDataSource(val onPostBundle: suspend (BundleUploadRequest) -> Resource) : + DataSource { override suspend fun download(downloadRequest: DownloadRequest): Resource { TODO("Not yet implemented") @@ -233,7 +234,7 @@ class BundleDataSource(val onPostBundle: suspend (BundleUploadRequest) -> Resour onPostBundle((request as BundleUploadRequest)) } -class UrlRequestDataSource(val onUrlRequestSend: suspend (UrlUploadRequest) -> Resource) : +internal class UrlRequestDataSource(val onUrlRequestSend: suspend (UrlUploadRequest) -> Resource) : DataSource { override suspend fun download(downloadRequest: DownloadRequest): Resource { diff --git a/engine/src/test/java/com/google/android/fhir/sync/FhirSyncWorkerTest.kt b/engine/src/test/java/com/google/android/fhir/sync/FhirSyncWorkerTest.kt index 8932338bb1..ba51d5d5e6 100644 --- a/engine/src/test/java/com/google/android/fhir/sync/FhirSyncWorkerTest.kt +++ b/engine/src/test/java/com/google/android/fhir/sync/FhirSyncWorkerTest.kt @@ -42,7 +42,7 @@ import org.robolectric.annotation.Config @RunWith(RobolectricTestRunner::class) @Config(manifest = Config.NONE) -class FhirSyncWorkerTest { +internal class FhirSyncWorkerTest { private lateinit var context: Context class PassingPeriodicSyncWorker(appContext: Context, workerParams: WorkerParameters) : diff --git a/engine/src/test/java/com/google/android/fhir/sync/upload/request/RequestGeneratorTestUtils.kt b/engine/src/test/java/com/google/android/fhir/sync/upload/request/RequestGeneratorTestUtils.kt index 6f8bc949dd..b9ea837690 100644 --- a/engine/src/test/java/com/google/android/fhir/sync/upload/request/RequestGeneratorTestUtils.kt +++ b/engine/src/test/java/com/google/android/fhir/sync/upload/request/RequestGeneratorTestUtils.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 Google LLC + * Copyright 2023-2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,7 +26,7 @@ import org.hl7.fhir.r4.model.HumanName import org.hl7.fhir.r4.model.Patient import org.hl7.fhir.r4.model.ResourceType -object RequestGeneratorTestUtils { +internal object RequestGeneratorTestUtils { fun LocalChange.toPatch() = Patch( From 201a87496a70e6ce0d03b1b20f970fb0391fb301 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 18:46:31 +0100 Subject: [PATCH 9/9] Bump androidx.build.gradle.gcpbuildcache (#2390) Bumps androidx.build.gradle.gcpbuildcache from 1.0.0-beta05 to 1.0.0-beta07. --- updated-dependencies: - dependency-name: androidx.build.gradle.gcpbuildcache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index e730ebe50b..bc56f5a9cc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -3,7 +3,7 @@ import androidx.build.gradle.gcpbuildcache.GcpBuildCacheServiceFactory plugins { id("com.gradle.enterprise") version ("3.10") - id("androidx.build.gradle.gcpbuildcache") version "1.0.0-beta05" + id("androidx.build.gradle.gcpbuildcache") version "1.0.0-beta07" id("org.gradle.toolchains.foojay-resolver-convention") version ("0.5.0") }