Skip to content

Commit 158c90c

Browse files
authored
Merge pull request #135 from patientsknowbest/feature/PHR-15452-add-support-for-both-search-parameters
Support both aidbox and FHIR SearchParameter API PHR-15452
2 parents bbf97fd + 4226461 commit 158c90c

17 files changed

+749
-126
lines changed

README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,23 @@ Trial license can be obtained either
5353
- we can also issue our own development licenses from now on, ask around for these, or try accessing the [user portal](https://aidbox.app/ui/portal#/project/f07750f6-28e3-44be-a8f8-c2004ef2b1ea/license)
5454

5555
```sh
56-
$ (cd scripts && AIDBOX_LICENSE=<your-aidbox-license> docker-compose up -d)
57-
$ make testacc
56+
(cd scripts && AIDBOX_LICENSE=<your-aidbox-license> docker-compose up -d)
57+
make testacc
5858
```
5959

6060
Erase the test cache in case you don't have code changes but still want to run the tests from scratch
6161
(e.g. you only have environmental changes, like updating the docker image):
6262
`go clean -testcache`
6363

64+
## Testing the provider with legacy modes of operation
65+
66+
In case you want to test functionality that predates schema mode and is not compatible with it, use the compose
67+
file docker-compose-legacy.yaml
68+
```shell
69+
docker compose -f scripts/docker-compose.yaml up
70+
TF_ACC_AIDBOX_MODE=legacy make testacc
71+
```
72+
6473
## Trying out the provider without releasing
6574

6675
Once the provider is in a suitable state, further to the above testing you can try it out by pointing terraform to look

aidbox/search_parameter.go

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,18 @@ import (
77
"log"
88
)
99

10+
// SearchParameter Aidbox customized representation of FHIR "SearchParameter"
1011
type SearchParameter struct {
1112
ResourceBase
12-
ResourceType string `json:"resourceType,omitempty"`
13-
Name string `json:"name"`
14-
Type SearchParameterType `json:"type"`
15-
Expression string `json:"expression"`
16-
Description string `json:"description"`
17-
Url string `json:"url"`
18-
Status string `json:"status"`
19-
Code string `json:"code"`
20-
Base []string `json:"base"`
13+
Name string `json:"name"`
14+
Module string `json:"module,omitempty"`
15+
Type SearchParameterType `json:"type"`
16+
ExpressionElements [][]interface{} `json:"expression"`
17+
Resource Reference `json:"resource"`
2118
}
2219

2320
func (*SearchParameter) GetResourcePath() string {
24-
return "fhir/SearchParameter"
21+
return "SearchParameter"
2522
}
2623

2724
type SearchParameterType int

aidbox/search_parameter_v2.go

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package aidbox
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/json"
7+
"log"
8+
)
9+
10+
// SearchParameterV2 Represents the FHIR R4 spec "SearchParameter"
11+
type SearchParameterV2 struct {
12+
ResourceBase
13+
ResourceType string `json:"resourceType,omitempty"`
14+
Name string `json:"name"`
15+
Type SearchParameterTypeV2 `json:"type"`
16+
Expression string `json:"expression"`
17+
Description string `json:"description"`
18+
Url string `json:"url"`
19+
Status string `json:"status"`
20+
Code string `json:"code"`
21+
Base []string `json:"base"`
22+
}
23+
24+
func (*SearchParameterV2) GetResourcePath() string {
25+
return "fhir/SearchParameter"
26+
}
27+
28+
type SearchParameterTypeV2 int
29+
30+
const (
31+
SearchParameterTypeV2String SearchParameterTypeV2 = iota
32+
SearchParameterTypeV2Number
33+
SearchParameterTypeV2Date
34+
SearchParameterTypeV2Token
35+
SearchParameterTypeV2Quantity
36+
SearchParameterTypeV2Reference
37+
SearchParameterTypeV2Uri
38+
SearchParameterTypeV2Composite
39+
)
40+
41+
func (t SearchParameterTypeV2) ToString() string {
42+
switch t {
43+
case SearchParameterTypeV2String:
44+
return "string"
45+
case SearchParameterTypeV2Number:
46+
return "number"
47+
case SearchParameterTypeV2Date:
48+
return "date"
49+
case SearchParameterTypeV2Token:
50+
return "token"
51+
case SearchParameterTypeV2Quantity:
52+
return "quantity"
53+
case SearchParameterTypeV2Reference:
54+
return "reference"
55+
case SearchParameterTypeV2Uri:
56+
return "uri"
57+
case SearchParameterTypeV2Composite:
58+
return "composite"
59+
}
60+
log.Panicf("Unexpected SearchParameterTypeV2 %d\n", t)
61+
return ""
62+
}
63+
64+
const ErrInvalidSearchParameterTypeV2 AidboxError = "Unsupported search parameter type"
65+
66+
func ParseSearchParameterTypeV2(typeString string) (SearchParameterTypeV2, error) {
67+
switch typeString {
68+
case "string":
69+
return SearchParameterTypeV2String, nil
70+
case "number":
71+
return SearchParameterTypeV2Number, nil
72+
case "date":
73+
return SearchParameterTypeV2Date, nil
74+
case "token":
75+
return SearchParameterTypeV2Token, nil
76+
case "quantity":
77+
return SearchParameterTypeV2Quantity, nil
78+
case "reference":
79+
return SearchParameterTypeV2Reference, nil
80+
case "uri":
81+
return SearchParameterTypeV2Uri, nil
82+
case "composite":
83+
return SearchParameterTypeV2Composite, nil
84+
default:
85+
return 0, ErrInvalidSearchParameterTypeV2
86+
}
87+
}
88+
89+
func (t SearchParameterTypeV2) MarshalJSON() ([]byte, error) {
90+
buffer := bytes.NewBufferString(`"`)
91+
buffer.WriteString(t.ToString())
92+
buffer.WriteString(`"`)
93+
return buffer.Bytes(), nil
94+
}
95+
96+
func (t *SearchParameterTypeV2) UnmarshalJSON(b []byte) error {
97+
var j string
98+
if err := json.Unmarshal(b, &j); err != nil {
99+
return err
100+
}
101+
tt, err := ParseSearchParameterTypeV2(j)
102+
if err != nil {
103+
return err
104+
}
105+
*t = tt
106+
return nil
107+
}
108+
109+
func (apiClient *ApiClient) CreateSearchParameterV2(ctx context.Context, searchParameter *SearchParameterV2) (*SearchParameterV2, error) {
110+
response := &SearchParameterV2{}
111+
return response, apiClient.createResource(ctx, searchParameter, response)
112+
}
113+
114+
func (apiClient *ApiClient) GetSearchParameterV2(ctx context.Context, id string) (*SearchParameterV2, error) {
115+
response := &SearchParameterV2{}
116+
return response, apiClient.getResource(ctx, id, response)
117+
}
118+
119+
func (apiClient *ApiClient) UpdateSearchParameterV2(ctx context.Context, q *SearchParameterV2) (*SearchParameterV2, error) {
120+
response := &SearchParameterV2{}
121+
return response, apiClient.updateResource(ctx, q, response)
122+
}
123+
124+
func (apiClient *ApiClient) DeleteSearchParameterV2(ctx context.Context, id string) error {
125+
return apiClient.deleteResource(ctx, id, &SearchParameterV2{})
126+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "aidbox_fhir_search_parameter Resource - terraform-provider-aidbox"
4+
subcategory: ""
5+
description: |-
6+
FHIR R4 SearchParameter https://hl7.org/fhir/R4/searchparameter.html
7+
---
8+
9+
# aidbox_fhir_search_parameter (Resource)
10+
11+
FHIR R4 SearchParameter https://hl7.org/fhir/R4/searchparameter.html
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `base` (List of String) The resource type(s) this search parameter applies to
21+
- `code` (String) Code used in URL
22+
- `description` (String) Natural language description of the search parameter
23+
- `expression` (String) FHIRPath expression that extracts the values, see https://hl7.org/fhir/fhirpath.html
24+
- `name` (String) Name of search parameter, used in search query string
25+
- `type` (String) Type of search parameter
26+
- `url` (String) Canonical identifier for this search parameter, represented as a URI (globally unique)
27+
28+
### Optional
29+
30+
- `status` (String) Value of draft | active | retired | unknown, see https://hl7.org/fhir/R4/valueset-publication-status.html
31+
32+
### Read-Only
33+
34+
- `id` (String) The ID of this resource.

docs/resources/search_parameter.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,23 @@ resource "aidbox_search_parameter" "example_extension" {
3232

3333
### Required
3434

35-
- `base` (List of String) The resource type(s) this search parameter applies to
36-
- `code` (String) Code used in URL
37-
- `description` (String) Natural language description of the search parameter
38-
- `expression` (String) FHIRPath expression that extracts the values, see https://hl7.org/fhir/fhirpath.html
35+
- `expression` (List of String) Expression for elements to search. Accepts three types: name of element / index / filter by pattern in collection. For filter, separator (|) must be used: {"system": "phone"} => "system|phone"
3936
- `name` (String) Name of search parameter, used in search query string
37+
- `reference` (Block List, Min: 1, Max: 1) Reference to resource this search param attached to (see [below for nested schema](#nestedblock--reference))
4038
- `type` (String) Type of search parameter
41-
- `url` (String) Canonical identifier for this search parameter, represented as a URI (globally unique)
4239

4340
### Optional
4441

45-
- `status` (String) Value of draft | active | retired | unknown, see https://hl7.org/fhir/R4/valueset-publication-status.html
42+
- `module` (String) Module name
4643

4744
### Read-Only
4845

4946
- `id` (String) The ID of this resource.
47+
48+
<a id="nestedblock--reference"></a>
49+
### Nested Schema for `reference`
50+
51+
Required:
52+
53+
- `resource_id` (String) The ID of the referenced resource
54+
- `resource_type` (String) The type of the referenced resource
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
resource "aidbox_fhir_search_parameter" "example_extension" {
2+
name = "custom-date"
3+
type = "date"
4+
base = ["Appointment"]
5+
code = "custom-date"
6+
expression = "Appointment.meta.extension.where(url = 'https://fhir.yourcompany.com/structuredefinition/custom-date').valueDateTime"
7+
description = "Search appointments by custom date expression"
8+
url = "https://fhir.yourcompany.com/searchparameter/custom-date"
9+
status = "active"
10+
}

internal/provider/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ func New(apiClient *aidbox.ApiClient) func() *schema.Provider {
5656
"aidbox_client": resourceClient(),
5757
"aidbox_db_migration": resourceDbMigration(),
5858
"aidbox_search_parameter": resourceSearchParameter(),
59+
"aidbox_fhir_search_parameter": resourceSearchParameterV2(),
5960
"aidbox_aidbox_subscription_topic": resourceAidboxSubscriptionTopic(),
6061
"aidbox_aidbox_topic_destination": resourceAidboxTopicDestination(),
6162
"aidbox_identity_provider": resourceIdentityProvider(),

internal/provider/provider_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,17 @@ func testAccPreCheck(t *testing.T) {
4646
// about the appropriate environment variables being set are common to see in a pre-check
4747
// function.
4848
}
49+
50+
// Used to skip tests that require a legacy mode of operation / incompatible with schema mode
51+
func requireLegacyMode(t *testing.T) {
52+
if os.Getenv("TF_ACC_AIDBOX_MODE") != "legacy" {
53+
t.Skip("Test is not compatible with schema mode, skipping")
54+
}
55+
}
56+
57+
// Used to skip tests that are incompatible with older modes of operation / schema mode
58+
func requireSchemaMode(t *testing.T) {
59+
if os.Getenv("TF_ACC_AIDBOX_MODE") == "legacy" {
60+
t.Skip("Test is not compatible with non-schema mode, skipping")
61+
}
62+
}

internal/provider/resource_aidbox_subscription_topic_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77

88
func TestAccAidboxSubscriptionTopic_triggerPatientEvents(t *testing.T) {
99
resource.Test(t, resource.TestCase{
10-
PreCheck: func() { testAccPreCheck(t) },
10+
PreCheck: func() { requireSchemaMode(t) },
1111
ProviderFactories: testProviderFactories,
1212
Steps: []resource.TestStep{
1313
{

internal/provider/resource_aidbox_topic_destination_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77

88
func TestAccAidboxTopicDestinaton_subscribeToPatientEvents(t *testing.T) {
99
resource.Test(t, resource.TestCase{
10-
PreCheck: func() { testAccPreCheck(t) },
10+
PreCheck: func() { requireSchemaMode(t) },
1111
ProviderFactories: testProviderFactories,
1212
Steps: []resource.TestStep{
1313
{

0 commit comments

Comments
 (0)