-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Most relevant are the tests. We want them to be already running when the code is first merged in. --------- Co-authored-by: Copybara <[email protected]>
- Loading branch information
1 parent
a72a839
commit 2853898
Showing
4 changed files
with
151 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Note: For syntax, see <https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-syntax> | ||
|
||
* @verily-src/fhirpathgo-eng-reviewers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
name: Build and Test | ||
on: | ||
pull_request: | ||
branches: | ||
- main | ||
|
||
jobs: | ||
build-test: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Setup Go | ||
uses: actions/setup-go@v5 | ||
with: | ||
# Use the central Go version defined in go.mod to make it easier | ||
# to perform upgrades. | ||
go-version-file: go.mod | ||
- name: Vet | ||
run: go vet -v -unreachable=false ./... | ||
- name: Build | ||
run: go build -v ./... | ||
- name: Test | ||
run: go test ./... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,99 @@ | ||
# fhirpath-go | ||
Go implementation of the FHIRPath specification, implemented directly with the google/fhir proto definitions. | ||
# FHIRPath | ||
|
||
This package contains a Go implementation of the [FHIRPath][fhirpath] specification, implemented directly with | ||
the [google/fhir][google-fhir] proto definitions. | ||
|
||
This package aims to be compliant with both: | ||
|
||
- the [N1 Normative Release](http://hl7.org/fhirpath/N1/) specification, and | ||
- the [R4 specifications](http://hl7.org/fhir/R4/fhirpath.html). | ||
|
||
## Import | ||
|
||
```go | ||
import "github.com/verily-src/fhirpath-go/fhirpath" | ||
``` | ||
|
||
## Usage | ||
|
||
A FHIRPath must be compiled before running it against a resource using the `Compile` method like so: | ||
|
||
```go | ||
expression, err := fhirpath.Compile("Patient.name.given") | ||
if err != nil { | ||
panic("error while compiling FHIRPath") | ||
} | ||
``` | ||
|
||
The compilation result can then be run against a resource: | ||
|
||
```go | ||
inputResources := []fhir.Resource{somePatient, someMedication} | ||
|
||
result, err := expression.Evaluate(inputResources) | ||
if err != nil { | ||
panic("error while running FHIRPath against resource") | ||
} | ||
``` | ||
|
||
As defined in the FHIRPath specification, the output of evaluation is a **Collection**. So, the | ||
result of Evaluate is of type `[]any`. As such, the result must be unpacked and cast to the desired | ||
type for further processing. | ||
|
||
### CompileOptions and EvaluateOptions | ||
|
||
Options are provided for optional modification of compilation and evaluation. There is currently | ||
support for: | ||
|
||
- adding custom functions during Compile time | ||
- adding custom external constant variables | ||
|
||
#### To add a custom function | ||
|
||
The constraints on the custom function are as follows: | ||
|
||
- First argument must be `system.Collection` | ||
- Arguments that follow must be either a fhir proto type or primitive system type | ||
|
||
```go | ||
customFn := func (input system.Collection, args ...any) (system.Collection error) { | ||
fmt.Print("called custom fn") | ||
return input, nil | ||
} | ||
expression, err := fhirpath.Compile("print()", WithFunction("print", customFn)) | ||
``` | ||
|
||
#### To add external constants | ||
|
||
The constraints on external constants are as follows: | ||
|
||
- Must be a fhir proto type, primitive system type, or `system.Collection` | ||
- If you pass in a collection, contained elements must be fhir proto or system type. | ||
|
||
```go | ||
customVar := system.String("custom variable") | ||
result, err := expression.Evaluate([]fhir.Resource{someResource}, WithConstant("var", customVar)) | ||
``` | ||
|
||
### System Types | ||
|
||
The FHIRPath [spec](http://hl7.org/fhirpath/N1/#literals) defines the following custom System types: | ||
|
||
- Boolean | ||
- String | ||
- Integer | ||
- Decimal | ||
- Quantity | ||
- Date | ||
- Time | ||
- DateTime | ||
|
||
FHIR Protos get implicitly converted to the above types according to this | ||
[chart](http://hl7.org/fhir/R4/fhirpath.html#types), when used in some FHIRPath expressions. | ||
|
||
### Things to be aware of | ||
|
||
FHIRPath is not the most intuitive language, and there are some quirks. See [gotchas](gotchas.md). | ||
|
||
[fhirpath]: http://hl7.org/fhirpath/ | ||
[google-fhir]: https://github.com/google/fhir |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# FHIRPath Gotcha’s | ||
|
||
## Empty collections are propagated | ||
|
||
* In FHIRPath, whenever an empty collection is encountered, rather than raising an error it gets propagated throughout the rest of the expression. This may make some issues difficult to catch. | ||
* Eg. given `Patient.name` -> `{}`, `Patient.name.family + ' MD'` -> `{}` | ||
|
||
## Equality sometimes returns an empty collection { }, rather than false | ||
|
||
* If either collection is empty | ||
* If the **precision_ _**of Date, Time, or DateTime objects are mismatched | ||
* If the **dimension** of a Quantity unit is mismatched | ||
|
||
## FHIR type specifiers are case-sensitive | ||
|
||
* **Primitive** types are denoted with lower case specifiers. | ||
* **Primitive** types that are written as upper case will be resolved as **System** types, not **FHIR** types. | ||
* Eg. `Patient.birthDate is date = **true**` but `Patient.birthDate is Date = **false**` | ||
* Case should match what’s listed [here](https://www.hl7.org/fhir/r4/datatypes.html) | ||
* System types always begin with an uppercase letter | ||
|
||
## `As` Expression is _not_ a filter, expects singleton input | ||
|
||
* The as expression (`Observation.value as integer`) expects a singleton as input. For example, if you pass in a resource with multiple value fields, it will raise an error. | ||
* It doesn’t filter out things that don’t match the type. For this purpose, the `where()` function should be used -> `where(value is integer)` |